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. 会员制实现C2B定制有机农产品,被中粮我买投资的良食网这样卖有机生鲜

    前几天,中粮我买网战略投资了位于深圳的有机生鲜自营平台良食网,宣布双方将会在供应链上展开合作.然而良食网对大家来说还是比较陌生的,为此36氪专访了良食网的创始人唐忠. 良食网成立于2011年,是一家以 ...

  2. 必须正确理解的---ng指令中的compile与link函数解析

    这个绝对是深入的知识,但看完之后,对NG的理解就很利害啦. http://www.ifeenan.com/angularjs/2014-09-04-%5B%E8%AF%91%5DNG%E6%8C%87 ...

  3. git merge 合并分支

    git merge 用来做分支合并,将其他分支中的内容合并到当前分支中.比如分支结构如下: master / C0 ---- C1 ---- C2 ---- C4 \ C3 ---- C5 \ iss ...

  4. 那些年不错的Android开源项目

    那些年不错的Android开源项目 转载自 eoe 那些年不错的Android开源项目-个性化控件篇 第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.Acti ...

  5. JVM的GC理论详解

    GC的概念 GC:Garbage Collection 垃圾收集.这里所谓的垃圾指的是在系统运行过程当中所产生的一些无用的对象,这些对象占据着一定的内存空间,如果长期不被释放,可能导致OOM(堆溢出) ...

  6. DataGrid排序

    DataGrid是ASP.NET中非常重要的一个控件.它能方便的让我们实现编辑.排序功能:但是排序功能默认的是升序(ASC),能不能让DataGrid同时实现升降序排列呢?这篇文章将给你一个比较好的解 ...

  7. 修改setInterval作用域

    Hello,今天和大家分享如何修改setInterval作用域. 0.引子 最近在做一个项目的时候需要开发一个图片轮播显示的组件,在实现过程中遇到了关于setInterval作用域的问题. Slide ...

  8. OI分类

    黑字:认识 红字:要学 未添加:要学 ├─模拟├─字符串│    ├─字符串基础│    ├─manacher│    ├─kmp│    ├─trie│    ├─ac自动机│    ├─后缀数组( ...

  9. BZOJ3925: [Zjoi2015]地震后的幻想乡

    Description 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任 ...

  10. BZOJ4408: [Fj Winter Camp 2016]神秘数

    Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13}, 1 = 1 2 = 1+1 3 = 1+1+1 4 = 4 5 = ...