摘要:在trace yii框架源码的时候,遇到__set()魔术方法的使用,有些疑惑,所以写了demo来测试,果然发现了玄机,整理如下。
1. 先来看看书本上讲魔术方法__set()是怎么用的
使用__set()魔术方法的目的是:在对象外部 为私有属性赋值,不能获取私有属性的值。
函数原型:
void __set(string name,mixed value)
写个demo:
class CModule {
private $_components = '';
public function __set($name,$value){
$this->$name = $value;
}
public function echoPrivate(){
echo $this->_components;
}
}
$module = new CModule();
$module->_components = 'request';
$module->echoPrivate();
//打印结果是
//request
解释:要给对象的私有属性赋值的时候,本来是不行的(书里面讲类的封装性的时候,提出的概念),但是我们声明了魔术方法__set(),所以当给私有属性赋值的时候,就会调用这个方法。因为这个方法在对象内部,所以可以对私有属性赋值。要读取这个对象的私有属性的值,也不能直接读取,要通过该公有方法间接读取。
这就是魔术方法最普通的用法。
那么再来看看这种情况,如果对私有属性的赋值在构造函数里面,会发生什么。
2. 也看起来挺正常的用法,但有些小疑虑
写个demo:
class CModule {
private $_components = '';
public function __construct($config=null){
foreach($config as $key=>$value)
$this->$key=$value;
}
public function __set($name,$value){
$this->$name = $value . "__set";
}
public function echoPrivate(){
echo $this->_components;
}
}
$config = array(
'_components'=>'request'
);
$module = new CModule($config);
$module->echoPrivate();
//打印结果是
//request
解释:这次是在new出对象的时候,顺便调用构造函数对私有属性赋值的,打印结果是’request’,没有调用魔术方法__set(),这也是很合乎情理的,因为构造函数里面对私有属性赋值本身就是合法的。
这样对私有属性赋值的时候,是没有调用魔术方法__set()的。
3. yii框架里面的用法,比较不走寻常路
class CModule {
public function __construct($config=null){
foreach($config as $key=>$value)
$this->$key=$value;
}
public function __set($name,$value){
$this->$name = $value . "__set";
}
}
$config = array(
'_components'=>'request'
);
$module = new CModule($config);
echo $module->_components;
//打印结果是
//request__set
yii框架初始化的时候,将配置数组里面的配置项复制进CWepAppliaction的属性的时候就是这样做的。
他里面并没有声明私有变量,然后在构造函数里面执行赋值,这时候就会调用魔术方法。是不是感觉优点绕。
暂时没有找到一个标准的定律,先记下来。