Trait是自 PHP 5.4.0 起添加的一個新特性,是 PHP 多重繼承的一種解決方案。例如,需要同時繼承兩個 Abstract Class, 這將會是件很麻煩的事情,Trait 就是為了解決這個問題。
下面是一個例子,類Demo同時繼承了Test1、Test2:
<?php
trait Test1{
public function add($a, $b){
echo $a + $b;
}
}
trait Test2{
public function sub($a, $b){
echo $a - $b;
}
}
class Demo{
use Test1,Test2;
}
$obj = new Demo();
$obj->add(3, 5); // 8
$obj->sub(3, 5); // -2
一些特性
1、優(yōu)先級:當(dāng)前類 > trait > 基類 。 即當(dāng)前類中的方法會覆蓋 trait 方法,而 trait 方法又覆蓋了基類中的方法。
2、多個 trait: 通過逗號分隔,在 use 聲明列出多個 trait,可以都插入到一個類中。
3、沖突的解決:
如果兩個 trait 都插入了一個同名的方法,如果沒有明確解決沖突將會產(chǎn)生一個致命錯誤。
為了解決多個 trait 在同一個類中的命名沖突,需要使用 insteadof 操作符來明確指定使用沖突方法中的哪一個。
以上方式僅允許排除掉其它方法,as 操作符可以將其中一個沖突的方法以另一個名稱來引入。
<?php
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}
trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}
class Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
}
class Aliased_Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}
?>
4、trait嵌套:Trait 之間也可以相互的嵌套:在 trait 定義時通過使用一個或多個 trait,它能夠組合其它 trait 中的部分或全部成員。
5、Trait 的抽象方法:我們可以在 Trait 中聲明需要實現(xiàn)的抽象方法,這樣能使使用它的 Class 必須實現(xiàn)它。
需要注意的幾點:
Trait 會覆蓋調(diào)用類繼承的父類方法
Trait 無法如 Class 一樣使用 new 實例化
單個 Trait 可由多個 Trait 組成
在單個 Class 中,可以使用多個 Trait
Trait 支持修飾詞(modifiers),例如 final、static、abstract
我們能使用 insteadof 以及 as 操作符解決 Trait 之間的沖突
一些看法
坦白講,第一眼看到 Trait 對它并沒有任何好感。PHP5 以來帶來的新特性已經(jīng)足夠得多,而且讓開發(fā)者們有點應(yīng)接不暇。
同時,Trait 更像是程序員的“語法糖”,然而它提供便利的同時可能會造成巨大的隱患。
針對類中已經(jīng)實現(xiàn)的方法,Trait 沒有效果。