什么是trait
自 PHP 5.4.0 起,PHP 實(shí)現(xiàn)了一種代碼復(fù)用的方法,稱為 trait。
Trait 是為類似 PHP 的單繼承語言而準(zhǔn)備的一種代碼復(fù)用機(jī)制。Trait 為了減少單繼承語言的限制,使開發(fā)人員能夠自由地在不同層次結(jié)構(gòu)內(nèi)獨(dú)立的類中復(fù)用 method。Trait 和 Class 組合的語義定義了一種減少?gòu)?fù)雜性的方式,避免傳統(tǒng)多繼承和 Mixin 類相關(guān)典型問題。
Trait 和 Class 相似,但僅僅旨在用細(xì)粒度和一致的方式來組合功能。 無法通過 trait 自身來實(shí)例化。它為傳統(tǒng)繼承增加了水平特性的組合;也就是說,應(yīng)用的幾個(gè) Class 之間不需要繼承。
其實(shí)就是一句話,彌補(bǔ)了php不能多繼承的問題
trait和當(dāng)前類
trait Goods {
public function goodsInfo(){
echo 'trait-goodsInfo';
}
}
class c {
use Goods; // 相當(dāng)與trait Goods給引入當(dāng)前類,就可以使用其中的goodsInfo方法
public function goodsAttr(){
echo 'goodsAttr';
}
}
$c = new c();
echo $c->goodsInfo(); // 'trait-goodsInfo'
echo $c->goodsAttr(); // 'goodsAttr'
可見,對(duì)象調(diào)用一個(gè)方法若找不到,就會(huì)去當(dāng)前類引入的trait中去找.
當(dāng)類c中如果和引入的trait中有同名的方法,則優(yōu)先會(huì)讀取當(dāng)前c中的方法,如下所示:
trait Goods {
public function goodsInfo(){
echo 'trait-goodsInfo';
}
}
class c {
use Goods; // 相當(dāng)與trait Goods給引入當(dāng)前類,就可以使用其中的goodsInfo方法
public function goodsAttr(){
echo 'goodsAttr';
}
public function goodsInfo(){
echo 'c-goodsInfo';
}
}
$c = new c();
echo $c->goodsInfo(); // 'c-goodsInfo'
echo $c->goodsAttr(); // 'goodsAttr'
結(jié)果是'c-goodsInfo'.可見,當(dāng)前類的優(yōu)先級(jí)高于trait.
trait和繼承
trait Goods {
public function goodsInfo(){
echo 'trait-goodsInfo';
}
}
class p{
public function goodsInfo(){
echo 'p-goodsInfo';
}
}
class c extends p{
use Goods; // 相當(dāng)與trait Goods給引入當(dāng)前類,就可以使用其中的goodsInfo方法
}
$c = new c();
echo $c->goodsInfo(); // 'trait-goodsInfo'
結(jié)果是'trait-goodsInfo' ,可見trait的優(yōu)先級(jí)高于繼承。
trait中的this
trait Good{
public function getName(){
echo "My name is " . $this->name;
}
}
class Person{
public $name = '王大錘';
use Good;
}
$p = new Person();
$p->getName(); // My name is 王大錘
可見,trait中的this依然是當(dāng)前調(diào)用的對(duì)象p。
trait中使用trait
trait Hello {
public function sayHello(){
echo 'Hello';
}
}
trait World {
public function sayWorld(){
echo 'World';
}
}
trait HelloWorld {
//使用多個(gè)trait
use Hello,World;
}
class MyHelloWorld{
use HelloWorld;
}
$obj = new MyHelloWorld();
$obj->sayHello(); // Hello
$obj->sayWorld(); // World
關(guān)于trait的用法先介紹這么多吧! 更多細(xì)節(jié)請(qǐng)看官網(wǎng)trait的解釋
小結(jié)
- Trait 無法如 Class 一樣使用 new 實(shí)例化
- 在單個(gè) Class 中,可以使用多個(gè) Trait
- 當(dāng)前類的優(yōu)先級(jí)高于trait,trait的優(yōu)先級(jí)高于繼承。
當(dāng)前類>trait>繼承類 - 使用trait時(shí)候應(yīng)該堅(jiān)決避免命名沖突,尤其是同時(shí)使用多個(gè)trait時(shí)。