常用底层知识 - Object 基类的特性 ¶
作者:KK
发表日期:2016.12.8
Yii框架里(我是指@yii目录下,这才是框架)99%的类的祖先类都是yii\base\Object
或者yii\base\Component
,这两个类都有相同之处,可以说一个是基础版,一个是加强版
本文主要先讲讲基础版的yii\base\Object
特性1:可以在new的时候进行属性注入 ¶
我们先自己定义一个app\Test
类来继承yii\base\Object
进行测试
namespace app;
class Test extends \yii\base\Object{
public $name;
public $age;
}
然后在控制器里玩玩看效果:
$config = [
'name' => 'Jay',
'age' => 26,
];
$test = new Test($config);
print_r([$test->name, $test->age]);
好了一看就懂,不废话
特性2:提供空的init方法进行初始化 ¶
通常如果我们要在Test的构造方法__construct
做点事,就无法使用属性注入这个特性了,不信你看看@yii\base\Object.php的public function __construct
这里,你怎么能随便重写呢?
那要在new的时候自动执行代码怎么办?
用public function init(){}
,在Object基类里这个init是一个空方法,用于给子类重写的,__construct后会自动调用init,来来试试:
namespace app;
class Test extends \yii\base\Object{
public $name;
public $age;
public function init(){
$this->name = 'May';
}
}
测试代码,客官请直接复制:
$test = new Test();
echo $test->name; //May
- 重要知识点:没啥事别重写__construct,建议重写init来做初始化操作
倒是__descruct
没这个问题,随你便
特性3:getter支持 ¶
当继承Object的类有一个public function getXxx()
方法时,可以直接通过echo $obj->xxx
来输出getXxx
方法的返回值,例:
namespace app;
class Test extends \yii\base\Object{
public $sex = '男';
private $_age = 99;
public function getAge(){
if($this->sex == '女'){
throw new \Exception('怎么可以向女生问年龄!');
}
return $this->_age;
}
}
客官是不是想继续复制调用代码呀
$test = new Test();
echo $test->age;
$test->sex = '女';
echo $test->age;
总结:关键是方法要public,然后是get开头,get后面的单词就是访问的属性名,方法不能有参数
特性4:setter也支持 ¶
其实这跟特性3是同一个特性,只是我想分开两小节来说,以免一眼看见离下一个大标题那么远,感觉学习量很大的样子,你可以一小点一小点学的~
与getter一样的逻辑,这个setter就是当你定义了public function setAge($value)
的时候,执行$obj->age = 9
就会触发setAge($value)
方法,而这个$value就是赋过来的值
完善一下Test类:
namespace app;
class Test extends \yii\base\Object{
public $sex = '男';
private $_age = 99;
public function getAge(){
if($this->sex == '女'){
throw new \Exception('怎么可以向女生问年龄!');
}
return $this->_age;
}
public function setAge($age){
if($age < 0){
throw new \Exception('无效的年龄');
}
$this->_age = $age;
}
}
控制器测试代码:
$test = new Test();
$test->age = 5;
echo $test->age;
$test->age = -1; //赋的值有问题,引发异常
总结:方法也要public,命名前缀则是set开头,接收一个$value参数处理等号赋的值
getter和setter的好处是让使用这个类的人只管知道有什么属性,细节不关心,要值就访问属性名,要赋值就直接=
号赋值,不用调方法传参数
虽然底层通过__get
和__set
实现这个特性牺牲了点性能,但我觉得这个牺牲量其实不大,通常带来的好处性价比还是很值得的