PHP Trait
阿新 • • 發佈:2019-01-28
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";
}
?>