Yii2的深入学习--yii\base\Object 类

之前我们说过 Yii2 中大多数类都继承自 yii\base\Object,今天就让我们来看一下这个类。

Object 是一个基础类,实现了属性的功能,其基本内容如下:

<?php
namespace yii\base;

use Yii;

/**
 * Object 是一个基础类,实现了属性的功能
 * Yii最基础的类,大多数类都继承了该类
 */
class Object implements Configurable
{
    /**
     * 获取静态方法调用的类名。返回类的名称,如果不是在类中调用则返回 FALSE。
     */
    public static function className()
    {
        ...
    }

    /**
     * Constructor.
     */
    public function __construct($config = [])
    {
        ...
    }

    /**
     * 初始化对象
     */
    public function init()
    {
    }

    /**
     * 魔术方法,实现 getter
     */
    public function __get($name)
    {
        ...
    }

    /**
     * 魔术方法,实现 setter
     */
    public function __set($name, $value)
    {
        ...
    }

    /**
     * 魔术方法,实现 isset,基于 getter 实现,有 getter 方法的属性才算存在
     */
    public function __isset($name)
    {
        ...
    }

    /**
     * 魔术方法,实现 unset,基于 setter 实现,有 setter 方法的属性才能 unset 掉
     */
    public function __unset($name)
    {
        ...
    }

    /**
     * Calls the named method which is not a class method.
     */
    public function __call($name, $params)
    {
        ...
    }

    /**
     * 检查对象或类是否具有 $name 属性,如果 $checkVars 为 true,则不局限于是否有 getter/setter
     */
    public function hasProperty($name, $checkVars = true)
    {
        ...
    }

    /**
     * 检查对象或类是否能够获取 $name 属性,如果 $checkVars 为 true,则不局限于是否有 getter
     */
    public function canGetProperty($name, $checkVars = true)
    {
        ...
    }

    /**
     * 检查对象或类是否能够设置 $name 属性,如果 $checkVars 为 true,则不局限于是否有 setter
     */
    public function canSetProperty($name, $checkVars = true)
    {
        ...
    }

    /**
     * 检查对象或类是否具有 $name 方法
     */
    public function hasMethod($name)
    {
        ...
    }
}

如果想看详细的注释的话,可以访问 https://github.com/ReadCode/yii2-2.0.3-annotated/blob/master/framework/base/Object.php

从上面的内容中,我们可以看到 Object 类重写了 __get 和 __set 方法,下面我们来详细看下这两个方法:

    /**
     * Returns the value of an object property.
     *
     * Do not call this method directly as it is a PHP magic method that
     * will be implicitly called when executing `$value = $object->property;`.
     *
     * 魔术方法,实现 getter
     *
     * @param string $name the property name
     * @return mixed the property value
     * @throws UnknownPropertyException if the property is not defined
     * @throws InvalidCallException if the property is write-only
     * @see __set()
     */
    public function __get($name)
    {
        $getter = ‘get‘ . $name;
        if (method_exists($this, $getter)) {
            // 对象存在 $getter 方法,就直接调用
            return $this->$getter();
        } elseif (method_exists($this, ‘set‘ . $name)) {
            // 如果存在 ‘set‘ . $name 方法,就认为该属性是只写的
            throw new InvalidCallException(‘Getting write-only property: ‘ . get_class($this) . ‘::‘ . $name);
        } else {
            // 否则认为该属性不存在
            throw new UnknownPropertyException(‘Getting unknown property: ‘ . get_class($this) . ‘::‘ . $name);
        }
    }

    /**
     * Sets value of an object property.
     *
     * Do not call this method directly as it is a PHP magic method that
     * will be implicitly called when executing `$object->property = $value;`.
     *
     * 魔术方法,实现 setter
     *
     * @param string $name the property name or the event name
     * @param mixed $value the property value
     * @throws UnknownPropertyException if the property is not defined
     * @throws InvalidCallException if the property is read-only
     * @see __get()
     */
    public function __set($name, $value)
    {
        $setter = ‘set‘ . $name;
        if (method_exists($this, $setter)) {
            // 对象存在 $setter 方法,就直接调用
            $this->$setter($value);
        } elseif (method_exists($this, ‘get‘ . $name)) {
            // 如果存在 ‘get‘ . $name 方法,就认为该属性是只读的
            throw new InvalidCallException(‘Setting read-only property: ‘ . get_class($this) . ‘::‘ . $name);
        } else {
            // 否则认为该属性不存在
            throw new UnknownPropertyException(‘Setting unknown property: ‘ . get_class($this) . ‘::‘ . $name);
        }
    }

基于上面的代码,我们可以看到,如果访问一个 Object 对象的某个属性, Yii会调用名为 get属性名() 的函数。如, SomeObject->Foo , 会自动调用 SomeObject->getFoo()。 如果修改某一属性,会调用相应的setter函数。 如, SomeObject->Foo = $someValue ,会自动调用 SomeObject->setFoo($someValue) 。

以 SomeObject 的 Foo 为例,如果只存在 getFoo() 方法,那它就是只读的,如果只存在 setFoo() 方法,那它就是只写的,只有两个方法都存在的时候才是既可读又可写的。

需要注意的一点是只有在读取和写入对象的一个不存在的成员变量时, __get() __set() 会被自动调用。 如果 Foo 是一个 public 的属性就不会经过 __get() 和  __set() 方法了。

所以通常属性是 private 的,举个例子如下:

class User extends yii\base\Object
{
    private $_name;

    public function getName()
    {
        return $this->_name;
    }

    public function setName($name)
    {
        $this->_name = trim($name);
    }
}

我们还可以在 get 和 set 方法中做一些特殊的处理。

除了 __get() __set() 之外, yii\base\Object 还提供了以下方法便于使用属性:

  • __isset() 用于测试属性值是否不为 null ,在 isset($object->property) 时被自动调用。 注意该属性要有相应的 getter。
  • __unset() 用于将属性值设为 null ,在 unset($object->property) 时被自动调用。 注意该属性要有相应的 setter。
  • hasProperty() 用于测试是否有某个属性。即,定义了 getter 或 setter。 如果 hasProperty() 的参数 $checkVars = true (默认为true), 那么只要具有同名的成员变量也认为具有该属性,如前面提到的 public $title 。
  • canGetProperty() 测试一个属性是否可读,参数 $checkVars 的意义同上。只要定义了 getter,属性即可读。 同时,如果 $checkVars 为 true 。那么只要类定义了成员变量,不管是 public, private 还是 protected, 都认为是可读。
  • canSetProperty() 测试一个属性是否可写,参数 $checkVars 的意义同上。只要定义了 setter,属性即可写。 同时,在 $checkVars 为 ture 。那么只要类定义了成员变量,不管是 public, private 还是 protected, 都认为是可写。

对 Yii2 源码有兴趣的同学可以关注项目 yii2-2.0.3-annotated,现在在上面已经添加了不少关于 Yii2 源码的注释,之后还会继续添加~

有兴趣的同学也可以参与进来,提交 Yii2 源码的注释。

时间: 2024-10-18 13:43:49

Yii2的深入学习--yii\base\Object 类的相关文章

Yii2的深入学习--yii\base\Event 类

根据之前一篇文章,我们知道 Yii2 的事件分两类,一是类级别的事件,二是实例级别的事件.类级别的事件是基于 yii\base\Event 实现,实例级别的事件是基于 yii\base\Component 实现. 今天先来看下类级别事件的实现,代码是 yii\base\Event 类. <?php namespace yii\base; /** * Event is the base class for all event classes. */ class Event extends Obje

JavaScript学习总结(十一)——Object类详解

一.Object类介绍 Object类是所有JavaScript类的基类(父类),提供了一种创建自定义对象的简单方式,不再需要程序员定义构造函数. 二.Object类主要属性 1.constructor:对象的构造函数. 2.prototype:获得类的prototype对象,static性质. 三.Object类主要方法 1.hasOwnProperty(propertyName) 判断对象是否有某个特定的属性.必须用字符串指定该属性,例如,obj.hasOwnProperty("name&q

Java基础学习之--理解Object类

看Java API的Object类, 一共11个方法.按使用的频度排名: toString() 这个方法最常用在打日志,定位代码问题. equals()和hashCode(), 这两个方法的使用经典例子是HashMap的源码 public V put(K key, V value) { if (table == EMPTY_TABLE) { inflateTable(threshold); } if (key == null) return putForNullKey(value); int h

黑马程序员--Java基础学习笔记【Object类、String类】

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- Object类 在Java类继承结构中,java.lang.Object类位于顶端. 所有类都直接或间接继承Object类. (接口不能继承Object类,接口中隐含定义了Object类的所有公共方法,但是全抽象) Object类型的引用变量可以指向任何类型对象. Object类成员方法 public String toString() { return getClass().getName(

Yii2的深入学习--继承关系

想要了解 Yii2 的话,一定要对 Yii2 中向相关类的继承关系有所了解.由于暂时读的代码有限,下面的图中只列出了部分继承关系,之后回跟着源码阅读的越来越多而增加 由上图可以看到 Yii2 中大多数类都继承自 yii\base\Object,实现了属性的功能. yii\base\Component yii\base\Event 和 yii\base\Behavior 都继承了 yii\base\Object,yii\base\Component 是一个实现了属性/事件和行为功能的基础类,yii

Yii2的深入学习--事件

我们先来看下事件在 Yii2 中的使用,如下内容摘自 Yii2中文文档 事件可以将自定义代码“注入”到现有代码中的特定执行点.附加自定义代码到某个事件,当这个事件被触发时,这些代码就会自动执行.例如,邮件程序对象成功发出消息时可触发 messageSent 事件.如想追踪成功发送的消息,可以附加相应追踪代码到 messageSent 事件. Yii 引入了名为 [[yii\base\Component]] 的基类以支持事件.如果一个类需要触发事件就应该继承 [[yii\base\Componen

Yii2的深入学习--自动加载机制

Yii2 的自动加载分两部分,一部分是 Composer 的自动加载机制,另一部分是 Yii2 框架自身的自动加载机制. Composer自动加载 对于库的自动加载信息,Composer 生成了一个 vendor/autoload.php 文件.你可以简单的引入这个文件,你会得到一个自动加载的支持. 在之前的文章,入口文件的介绍中,我们可以看到如下内容: // 引入 vendor 中的 autoload.php 文件,会基于 composer 的机制自动加载类 require(__DIR__ .

Yii2的深入学习--自动加载机制(转)

Yii2 的自动加载分两部分,一部分是 Composer 的自动加载机制,另一部分是 Yii2 框架自身的自动加载机制. Composer自动加载 对于库的自动加载信息,Composer 生成了一个 vendor/autoload.php 文件.你可以简单的引入这个文件,你会得到一个自动加载的支持. 在之前的文章,入口文件的介绍中,我们可以看到如下内容: // 引入 vendor 中的 autoload.php 文件,会基于 composer 的机制自动加载类 require(__DIR__ .

Java Object类学习笔记

看下Api文档的一些说明 public class Object Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects, including arrays, implement the methods of this class. Since: JDK1.0 从JDK1.0就已经存在的元老类,类结构的根,所有类的父类,所有类都实现了这个类的方法,包含