Trait和Class相似,但仅仅旨在用细粒度和一致的方式来组合功能。无法通过trait自身来实例化。它为传统继承增加了水平特性的组合。
对于方法: 当前类的成员>trait的方法>从基类继承的成员
对于变量: 当前类和基类中不能存在与trait重名的变量,否则会抛出fatal error。
<?php trait Mytrait { public $a = 100; public function test1() { echo "Mytrait Test1\n"; } public static function test2() { echo "Mytrait Test2\n"; } } class Base { public function test1() { echo "Base Test1\n"; } public static function test2() { echo "Base Test2\n"; } public static function test3() { echo "Base Test3\n"; } } class TraitExample1 extends Base{ use Mytrait; public function test1() { echo "TraitExample1 Test1\n"; } } $obj = new TraitExample1(); $obj->test1(); TraitExample1::test2(); $obj->test3(); echo $obj->a . "\n";
通过逗号分隔,在use声明中列出多个trait,可以都插入到一个类中。
如果两个trait都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。为了解决多个trait在同一个类中的命名冲突,需要使用insteadof操作符来明确指定使用冲突方法中的哪一个。或者使用as操作符,可以将其中一个冲突的方法以另一个名称来引入。
同样的,如果两个trait有同名的变量,如果该属性的定义兼容(同样的可见性及初始值)错误级别是E_STRICT,否则错误级别是E_ERROR.
且不能通过解决方法冲突的方式解决。
<?php trait Mytrait { public $a = 100; public function test1() { echo "Mytrait Test1\n"; } public static function test2() { echo "Mytrait Test2\n"; } } trait Mytrait2 { public function test1() { echo "Mytrait2 Test1\n"; } public static function test2() { echo "Mytrait2 Test2\n"; } } class TraitExample1{ use Mytrait,Mytrait2 { Mytrait::test1 insteadof Mytrait2; Mytrait2::test2 insteadof Mytrait; Mytrait::test2 as test2_2; } } $obj = new TraitExample1(); $obj->test1(); TraitExample1::test2(); $obj->test2_2(); echo $obj->a . "\n";
与Class中使用多个trait类似,trait也可以使用多个trait。冲突的解决方式也一致。
<?php trait Mytrait { public function test1() { echo "Mytrait Test1\n"; } public function test2() { echo "Mytrait Test2\n"; } } trait Mytrait2 { public function test1() { echo "Mytrait2 Test1\n"; } public function test2() { echo "Mytrait2 Test2\n"; } } trait Mytrait3 { use Mytrait, Mytrait2 { Mytrait::test1 insteadof Mytrait2; Mytrait2::test2 insteadof Mytrait; } } class TraitExample1{ use Mytrait3; } $obj = new TraitExample1(); $obj->test1(); $obj->test2();为了对使用的类施加强制要求,trait支持抽象方法的使用。
trait可以定义静态变量,静态方法。
<?php trait Mytrait { public static $in = 10; public function test1() { echo "Mytrait Test1\n"; } public function test2() { echo "Mytrait Test2\n"; } } trait Mytrait2 { public function test1() { echo "Mytrait2 Test1\n"; } public static function test2() { echo "Mytrait2 Test2\n"; } } trait Mytrait3 { use Mytrait, Mytrait2 { Mytrait::test1 insteadof Mytrait2; Mytrait::test2 insteadof Mytrait2; Mytrait2::test2 as test3; } } class TraitExample1{ use Mytrait3; } $obj = new TraitExample1(); $obj->test1(); $obj->test2(); TraitExample1::test3(); [root@hadoop1 php]# cat trait2.php <?php trait Mytrait { public static $in = 10; public function test1() { echo "Mytrait Test1\n"; } public function test2() { echo "Mytrait Test2\n"; } } trait Mytrait2 { public function test1() { echo "Mytrait2 Test1\n"; } public static function test2() { echo "Mytrait2 Test2\n"; } } trait Mytrait3 { use Mytrait, Mytrait2 { Mytrait::test1 insteadof Mytrait2; Mytrait::test2 insteadof Mytrait2; Mytrait2::test2 as test3; } } class TraitExample1{ use Mytrait3; } $obj = new TraitExample1(); $obj->test1(); $obj->test2(); TraitExample1::test3(); echo TraitExample1::$in;