常用底层知识 - 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.phppublic 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实现这个特性牺牲了点性能,但我觉得这个牺牲量其实不大,通常带来的好处性价比还是很值得的