trait

mac2022-06-30  26

PHP5.4实现了一种代码复用的方法称为Trait。

Trait为了减少单继承语言的限制,能够自由地在不同层次结构内独立的类中复用方法,Trait和Class组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。无法通过 trait 自身来实例化。一个类要应用trait需要使用use关键字,一个类可以应用多个trait,只需要在use关键字后用逗号分隔多个trait。 trait中也可以应用其他的trait。

<?php trait a{ function getA(){ return "a"; } } trait b{ function getB(){ return "b"; } } class Test{ use a,b; } $test=new Test(); echo $test->getA()."\n"; echo $test->getB()."\n"; trait c{ use a,b; } class Test2{ use c; } $test=new Test2(); echo $test->getA()."\n"; echo $test->getB()."\n"; ?>

如果trait和class中存在相同的成员,则优先级规则为,[当前类的成员->trait的成员->继承的成员]。

<?php trait a{ function getA(){ parent::getA(); echo "a in trait\n"; } } class Base{ function getA(){ echo "a in Base\n"; } } class Test extends Base{ use a; } class Test2 extends Base{ use a; function getA(){ echo "a in Test2\n"; } } $test=new Test(); $test->getA(); $test2=new Test2(); $test2->getA(); ?>

在应用多个trait时,如果插入了同名的方法,则需要解决冲突,否则会产生致命错误。解决冲突可以使用insteadof关键字来指明使用哪一个方法。还可以通过as关键字为某个方法引入别名,as关键字还可以调整方法的访问控制。

<?php trait A { public function printLower() { echo 'a'; } public function printUpper() { echo 'A'; } } trait B { public function printLower() { echo 'b'; } public function printUpper() { echo 'B'; } public function testAccess(){ } } class Test { use A, B { B::printLower insteadof A; A::printUpper insteadof B; B::printUpper as private upper; testAccess as protected; } } $test=new Test(); $test->printLower(); $test->printUpper(); //$test->upper(); //$test->testAccess(); ?>

trait还支持抽象方法,应用trait的类需要实现抽象方法,否则会产生致命错误。trait还支持静态成员。

<?php trait a{ function lower(){ return "a"; } abstract function upper(); public static function foo(){ echo "static function foo\n"; } } class Test{ use a; function upper(){ return "A"; } } $t=new Test(); echo $t->lower()."\n"; echo $t->upper()."\n"; Test::foo(); ?>

trait中可以定义属性,但是应用trait的类不能定义与之同名的属性,否则会产生致命错误,除非属性是兼容的,即访问控制和初始默认值都相同。PHP7.0之前即使属性兼容也会有E_STRICT的提醒。

<?php trait a{ public $var="a"; public $diff1="a"; public $diff2="a"; } class Test{ use a; public $var="a"; //public $diff1="b"; //protected $diff2="a"; } ?>
最新回复(0)