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

 namespace yii\base;

 use Yii;

 /**
  * Object is the base class that implements the *property* feature.
  * Object是一个基础类,实现了属性的功能
  * A property is defined by a getter method (e.g. `getLabel`), and/or a setter method (e.g. `setLabel`). For example,
  * the following getter and setter methods define a property named `label`:
  * 属性通过getter和setter方法定义,如下面的例子
  * ```php
  * private $_label; 定义私有的成员
  *
  * public function getLabel()
  * {
  *     return $this->_label; 通过getter方法取得_label的值
  * }
  *
  * public function setLabel($value)
  * {
  *     $this->_label = $value; 通过setter方法设置_label的值
  * }
  * ```
  *
  * Property names are *case-insensitive*.
  * 属性名是不区分大小写的
  * A property can be accessed like a member variable of an object. Reading or writing a property will cause the invocation
  * of the corresponding getter or setter method. For example,
  * 属性能够像一个成员变量一样被访问,读、写将会调用对应的getter或者setter方法
  * ```php
  * // equivalent to $label = $object->getLabel();
  * $label = $object->label;
  * // equivalent to $object->setLabel('abc');
  * $object->label = 'abc';
  * ```
  *
  * If a property has only a getter method and has no setter method, it is considered as *read-only*. In this case, trying
  * to modify the property value will cause an exception.
  * 如果一个属性只有getter方法,那么这个属性是只读的,如果试图修改这个属性的值,将会抛出异常
  * 能够调用 [[hasProperty()]], [[canGetProperty()]] and/or [[canSetProperty()]] 检查一个属性
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
  * @since 2.0
  */
 class Object implements Configurable
 {

     /**
      * Returns the fully qualified name of this class.
      * 获取静态方法调用的类名。返回类的名称,如果不是在类中调用则返回 FALSE。
      * @return string the fully qualified name of this class.
      */
     public static function className()
     {
         return get_called_class(); // get_called_class -- 后期静态绑定("Late Static Binding")类的名称
         // 就是用那个类调用的这个方法,就返回那个类,返回值中带有 namespace
     }

     /**
      * Constructor.
      * The default implementation does two things:
      * 构造方法实现了接口Configurable,通过传入的配置初始化对象,调用init()方法
      * - Initializes the object with the given configuration `$config`.
      * - Call [[init()]].
      *
      * If this method is overridden in a child class, it is recommended that
      * 如果构造函数在子类中重写,必须调用父类的方法,且最后一个参数为配置数组
      * - the last parameter of the constructor is a configuration array, like `$config` here.
      * - call the parent implementation at the end of the constructor.
      *
      * @param array $config name-value pairs that will be used to initialize the object properties
      */
     public function __construct($config = [])
     {
         // 根据 $config 内容初始化该对象
         if (!empty($config)) {
             Yii::configure($this, $config);
         }
         // 调用 init() 方法,继承该类的类可以重写 init 方法,用于初始化
         $this->init();
     }

     /**
      * Initializes the object.
      * 初始化对象
      * This method is invoked at the end of the constructor after the object is initialized with the
      * given configuration.
      * 在构造函数的末尾调用,可以重写 init 方法,用于初始化
      */
     public function init()
     {

     }

     /**
      * 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,在访问不存在的属性时调用,即成员变量设置为public时,不会被调用
      *
      * @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; //构造getter方法
         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,在访问不存在的属性时调用,即成员变量设置为public时,不会被调用
      *
      * @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; //构造setter方法
         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);
         }
     }

     /**
      * 检查属性是否被设置
      *
      * 魔术方法,实现 isset,用isset() 判断对象不可见的属性时(protected/private/不存在的属性)被调用
      * 基于 getter 实现,有 getter 方法的属性才算存在
      * @param string $name the property name or the event name
      * @return boolean whether the named property is set (not null).
      * @see http://php.net/manual/en/function.isset.php
      */
     public function __isset($name)
     {
         $getter = 'get' . $name;
         if (method_exists($this, $getter)) {
             // 判断是否有getter方法,且是否有返回值,有 getter 方法且获取的值不为 null,才认为该属性存在
             return $this->$getter() !== null;
         } else {
             return false;
         }
     }

     /**
      *
      * 魔术方法,实现 unset,在注销不可见的属性时(protected/private/不存在的属性)时被调用
      * 基于 setter 实现,有 setter 方法的属性才能 unset 掉
      * @param string $name 属性名
      * @throws InvalidCallException if the property is read only.
      * @see http://php.net/manual/en/function.unset.php
      */
     public function __unset($name)
     {
         $setter = 'set' . $name; //构造setter方法
         if (method_exists($this, $setter)) {
             // 如果setter方法存在,通过 setter 方法,将它设置为 null
             $this->$setter(null);
         } elseif (method_exists($this, 'get' . $name)) {
              // 如果存在 'get' . $name 方法,就认为该属性是只读的,抛出异常
             throw new InvalidCallException('Unsetting read-only property: ' . get_class($this) . '::' . $name);
         }
     }

     /**
      *重写了__call()方法,在调用不存在的方法时会调用此方法,抛出异常
      * @param string $name 方法名
      * @param array $params 方法参数
      * @throws UnknownMethodException when calling unknown method 异常
      * @return mixed the method return value
      */
     public function __call($name, $params)
     {
         throw new UnknownMethodException('Calling unknown method: ' . get_class($this) . "::$name()");
     }

     /**
      *
      * 检查对象或类是否具有 $name 属性,如果 $checkVars 为 true,则不局限于是否有 getter/setter
      *
      * @param string $name 属性名
      * @param boolean $checkVars 是否检查成员变量,默认为true
      * @return boolean 属性是否被定义
      * @see canGetProperty()
      * @see canSetProperty()
      */
     public function hasProperty($name, $checkVars = true)
     {
         return $this->canGetProperty($name, $checkVars) || $this->canSetProperty($name, false);
     }

     /**
      *
      * 检查对象或类是否能够获取 $name 属性,如果 $checkVars 为 true,则不局限于是否有 getter
      *
      * @param string $name 属性名
      * @param boolean $checkVars 是否检查成员变量,默认为true
      * @return boolean 属性是否可读
      * @see canSetProperty()
      */
     public function canGetProperty($name, $checkVars = true)
     {
         // property_exists — 检查对象或类是否具有该属性
         return method_exists($this, 'get' . $name) || $checkVars && property_exists($this, $name);
     }

     /**
      *
      * 检查对象或类是否能够设置 $name 属性,如果 $checkVars 为 true,则不局限于是否有 setter
      *
      * @param string $name 属性名
      * @param boolean $checkVars 是否检查成员变量,默认为true
      * @return boolean 属性是否可写
      * @see canGetProperty()
      */
     public function canSetProperty($name, $checkVars = true)
     {
         return method_exists($this, 'set' . $name) || $checkVars && property_exists($this, $name);
     }

     /**
      * 调用php的 `method_exists()`函数.
      * You may override this method when you implemented the php magic method `__call()`.
      *
      * 检查对象或类是否具有 $name 方法
      *
      * @param string $name 方法名
      * @return boolean 方法是否被定义
      */
     public function hasMethod($name)
     {
         return method_exists($this, $name);
     }

 }

Yii源码阅读笔记(五)的更多相关文章

  1. Yii源码阅读笔记(一)

    今天开始阅读yii2的源码,想深入了解一下yii框架的工作原理,同时学习一下优秀的编码规范和风格.在此记录一下阅读中的小心得. 每个框架都有一个入口文件,首先从入口文件开始,yii2的入口文件位于we ...

  2. Yii源码阅读笔记(三十五)

    Container,用于动态地创建.注入依赖单元,映射依赖关系等功能,减少了许多代码量,降低代码耦合程度,提高项目的可维护性. namespace yii\di; use ReflectionClas ...

  3. Yii源码阅读笔记(十五)

    Model类,集中整个应用的数据和业务逻辑——验证 /** * Returns the attribute labels. * 返回属性的标签 * * Attribute labels are mai ...

  4. Yii源码阅读笔记(二十五)

    Module类中剩余部分代码,通过控制器ID实例化当前模块的控制器,当前模块的Action方法的前置和后置方法: /** * This method is invoked right before a ...

  5. Yii源码阅读笔记(八)

    前面阅读了Yii2的两个基本类Object和Component,了解了Yii的三个重要概念属性.事件.行为,下面开始阅读Event类,Event类是所有事件类的基类: <?php /** * @ ...

  6. Yii源码阅读笔记(三)

    接着上次的继续阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— public static function getRootAlias($alias)// ...

  7. Yii源码阅读笔记(二)

    接下来阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— namespace yii; use yii\base\InvalidConfigExceptio ...

  8. Yii源码阅读笔记(三十四)

    Instance类, 表示依赖注入容器或服务定位器中对某一个对象的引用 namespace yii\di; use Yii; use yii\base\InvalidConfigException; ...

  9. Yii源码阅读笔记(三十三)

    ServiceLocator,服务定位类,用于yii2中的依赖注入,通过以ID为索引的方式缓存服务或则组件的实例来定位服务或者组件: namespace yii\di; use Yii; use Cl ...

随机推荐

  1. device unauthorized & ANDROID_ADB_SERVER_PORT 问题解决

    最近做安卓开发的时候,碰到了如下两个极品问题,刚开始晕头转向,仔细一研究终于解决了: FAQ1: C:\Users\xxx>adb shelladb: Env var ANDROID_ADB_S ...

  2. adb 卸载APP命令和杀死APP命令

    使用adb 卸载APP命令 在cmd命令行下,直接 输入 adb uninstall 包名 比如 adb uninstall com.ghstudio.BootStartDemo 杀死APP命令 先用 ...

  3. android 自定义相机画面倒立解决方案

    有部分手机的影像是倒立的,如何解决这个问题呢? 请看下面 public static void setCameraDisplayOrientation(Activity activity, int c ...

  4. loadrunner常见问题总结

    在玩Loadrunner时经常性的出现脚本录制为空的情况,下面是我总结出的解决办法: 1.在用loadrunner录制脚本时发现脚本录制为空,查找原因,我首先看. IE选项->连接->局域 ...

  5. codeforces 385 c

    Description Recently, the bear started studying data structures and faced the following problem. You ...

  6. POJ2823 Sliding Window(单调队列)

    题目要输出一个序列各个长度k的连续子序列的最大值最小值. 多次RMQ的算法也是能过的,不过单调队列O(n). 这题,队列存元素值以及元素下标,队尾出队维护单调性然后入队,队首出队保持新元素下标与队首元 ...

  7. 基于Extjs的web表单设计器 第七节——取数公式设计之取数公式的使用

    基于Extjs的web表单设计器 基于Extjs的web表单设计器 第一节 基于Extjs的web表单设计器 第二节——表单控件设计 基于Extjs的web表单设计器 第三节——控件拖放 基于Extj ...

  8. win7中资源管理器不能显示图片预览的解决方法

    在用xp的时候,在资源管理器里面预览图片文件是在普通不过的事情了.换到win7之后,图片文件一直不能预览,只是显示图标还挺烦的.肯定是哪里设置的不对,下午闲来无事,找到是哪里的问题了. 如果你也遇到相 ...

  9. 【POJ】3150 Cellular Automaton(矩阵乘法+特殊的技巧)

    http://poj.org/problem?id=3150 这题裸的矩阵很容易看出,假设d=1,n=5那么矩阵是这样的 1 1 0 0 1 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 ...

  10. SSH全注解开发

    web.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=&quo ...