面向对象 - trait代码共享 ¶
作者:KK
发表日期:2017.9.22
快速示例 ¶
//定义一个叫 CommonMethod 的trait,就像定义类一样
trait CommonMethod{
public $attr = 'abc';
public static function haha(){
return 'haha';
}
public function test1(){
return $this->name;
}
public function test2(){
return 222;
}
}
class A{
//引用上面的trait
use CommonMethod;
public $name = 'aaa';
public function test3(){
return 333;
}
}
class B{
//也引用上面的trait
use CommonMethod;
public $name = 'bbb';
public function test4(){
return 333;
}
}
$a = new A();
$b = new B();
print_r([
A::haha(), //haha 这是trait里的方法
$a->test1(), //aaa 也是trait的方法,可是返回了A类的name属性
$a->test2(), //222 trait的方法
$a->attr, //abc
B::haha(), //haha 这也是trait里的方法
$b->test1(), //bbb 道理同上
$b->test2(), //222
$b->attr, //abc
]);
上面例子中,A和B的类里面第一句就是use CommonMethod
,而这个CommonMethod
指的就是开头定义的trait CommonMethod
简单地说trait
关键词就是定义了一块公共代码,这块代码要起一个标识符于是我设定为CommonMethod,其它类要引用这块代码,就在类里面直接use代码标识符就行了,等于复制粘贴代码进来一样,然而这样并不是继承一个类,它不增加类的继承链,而仅仅是把另一块代码贴到自己身上扩展功能而已
这看上去跟继承的效果一模一样,但有时候我们既要继承某个类,又要与其它类拥有共同的某些方法,用这招就比较合适了
可以include ¶
你可以在一个单独的文件里定义trait,然后在别处include进来,就像include一个类一样而已
类里面可以use多个trait ¶
比如定义t1、t2和t3三个trait,可以下面这样直接多次use
class A{
use t1;
use t2;
use t3;
public $xxx = 123;
}
可以有命名空间 ¶
namespace app\common;
trait MyMethods{
//...
}
命名空间马上会在后面讲到,而引用的时候就是带上命名空间:use app\common\MyMethods
可以autoload ¶
如果use了一个不存在的trait,会自动触发autoload
其实就跟自动加载一个类一样,如果use CommonMethod33
,autoload会收到一个参数,值就是字符串“CommonMethod33”
如果use app\common\Methods
,则autoload收到的参数也是“app\common\Methods”
trait不能定义常量 ¶
虽说它就像一块公共代码一样可以被别的类use引用,但下面这样定义常量是支持的
trait Test{
const STATUS_ACTIVE = 1;
}