一直以来,在我的理解中,类的成员变量和属性就是同一个东西,直到看了《深入理解Yii2.0》才明白,类的成员变量和属性其实不是同一个概念,成员变量是就类的结构构成而言的概念,而属性是就类的功能逻辑而言的概念,而且两者没有必然的对应关系。
类的成员变量有public、protected、private三种类型,其中public类型的成员变量可以视为可读可写的属性,而另外两种类型的成员变量都不是属性,因为属性应该是可以在类外面进行访问的。
在Yii2.0中,yii\base\Object类通过PHP的魔术方法__get()和__set()来提供对属性的支持,源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public function __get($name) { $getter = 'get' . $name; if (method_exists($ this , $getter)) { //存在对应的getter方法 return $ this ->$getter(); } elseif (method_exists($ this , 'set' . $name)) { //只写属性 throw new InvalidCallException( 'Getting write-only property: ' . get_class($ this ) . '::' . $name); } else { //属性不存在 throw new UnknownPropertyException( 'Getting unknown property: ' . get_class($ this ) . '::' . $name); } } public function __set($name, $value) { $setter = 'set' . $name; if (method_exists($ this , $setter)) { //存在对应的setter方法 $ this ->$setter($value); } elseif (method_exists($ this , 'get' . $name)) { //只读属性 throw new InvalidCallException( 'Setting read-only property: ' . get_class($ this ) . '::' . $name); } else { //属性不存在 throw new UnknownPropertyException( 'Setting unknown property: ' . get_class($ this ) . '::' . $name); } } |
在yii2.0中,如果一个类需要支持属性,只要继承yii\base\Object类即可,以下举例说明:
1 2 3 4 5 6 7 8 | class user extends yii\ base \Object { public $name; private $addr; private $age; public function getAddress() { return $ this ->addr; } } |
这是一个很简单的类,根据类的成员变量和属性的概念可知,以上这个类中有三个成员变量:$name、$addr、$age,两个属性:$name、address。其中$name是可读可写属性,而address是只读属性,因为只存在getter方法而没有对应的setter方法。
假如我们在user类外面创建一个对象$user,通过$user->address来读取user类的address属性的时候,其实是遍历了一下user类的所有成员变量,没有找到address属性对应的成员变量的时候,再去调用__get()方法看看是否存在对应的getter方法,有则调用它。可以看到,当类的某个属性没有对应的成员变量的时候,通过$user->address这种方式来访问属性虽然比较方便但效率是比较低的,而使用$user->getAddress() 直接调用getter方法访问属性则可以省去遍历类成员变量的过程,比较高效。
除了__get()和__set()之外,yii\base\Object类还提供了与属性相关的其他方法:
__isset():判断属性是否不为null。
__unset():将属性值设置为null。
hasProperty():判断是否存在某个属性。
canGetProperty():判断某个属性是否可读。
canSetProperty():判断某个属性是否可写。
在yii2.0中,创建一个对象的时候,怎么给对象的所有属性赋值呢?Yii2.0提供了一个统一的配置对象的方式,那就是使用一个键值对形式的配置数组。那么yii2.0又是怎么支持这种配置方式的呢?通过查看源码可以看到,yii\base\Object类的构造函数__construct()中调用了Yii::configure()方法,该方法源码如下:
1 2 3 4 5 6 7 8 | public static function configure($ object , $properties) { foreach ($properties as $name => $value) { $ object ->$name = $value; } return $ object ; } |
其实很简单,就是遍历配置数组,配置数组的键名为对象的属性名,对应的值则作为属性值,逐一进行赋值。至于当对象的属性是对象或数组时,赋值操作该怎么进行就是setter函数的事了。
深入理解Yii2.0
本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/articles/9667883.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能