研究一下Traits
据说,为了弥补php单继承的不足,从PHP5.4起,引入了traits特性。使得php可以通过trait实现多重继承。
举例:
<?php
trait Foo {
public function test(){
echo "Testing";
}
}
class Person {
//在类中使用traits
use Foo;
public function newTest(){
echo "New testing";
}
}
//实例化对象
$person = new Person();
$person->newTest(); // New testing
$person->test(); // Testing
还可以像这样,同时引入多个Traits
<?php
trait includeTrait {
public function includeMethod(){
echo "这个trait将被别的trait包含";
}
}
trait firstTrait {
//trait中也可以包含trait
use includeTrait;
public function firstMethod(){
echo "method1";
}
}
trait secondTrait {
//trait中也可以使用抽象方法
abstract function secondMethod();
}
class Foo {
//同时使用多个trait
use firstTrait, secondTrait;
//重写抽象方法
public function secondMethod(){
echo "method2";
}
}
$foo = new Foo();
$foo->includeMethod(); //"这个trait将被别的trait包含"
$foo->firstMethod(); //"method1"
$foo->secondMethod(); //"method2"
如果命名冲突了呢?
<?php
trait T1 {
public function sameMethodName(){
echo "T1.";
}
}
trait T2 {
//包含了一个和T1同名的方法
private function sameMethodName(){
echo "T2.";
}
}
class Foo {
//同时使用T1和T2两个traits
use T1,T2 {
//使用T1中的sameMethodName而不是T2中的
T1::sameMethodName insteadof T2;
//将T2中的sameMethodName改名为anotherMethod;
T2::sameMethodName as public anotherMethod;
}
}
$foo = new Foo();
$foo->sameMethodName(); //"T1."
$foo->anotherMethod(); //"T2."
使用Trait实现单例模式
<?php
trait Singleton {
protected static $_instance = null;
final public function getInstance(){
if (is_null(self::$_instance)){
self::$_instance = new static(); //延迟静态绑定
}
return self::$_instance;
}
private function __construct(){
$this->init();
}
protected function init(){}
final private function __wakeup(){}
final private function __clone(){}
}
在类中使用该trait
<?php
class Foo {
use Singleton;
protected function init(){
echo "iw3c.com";
}
}
$foo1 = Foo::getInstance(); //输出iw3c.com
$foo2 = Foo::getInstance(); //无输出
总结:
- 可以使用use引入多个Traits
- 如果一个类引入了多个Traits,并且Traits中有同名的方法,在没有明确指定如何解决冲突时会产生一个致命错误,需要使用insteadof操作符来指定使用冲突方法中的哪一个方法,也可以使用as操作符将其中一个冲突方法以另一个名称引入。
- 使用as语法还可以用来调整方法的访问控制权限。
- Traits 和一个类的形为相似,但是不能被实例化。