自PHP5.4之前,PHP面向?qū)ο笮枰獜?fù)用代碼的方式是使用類的繼承。但PHP只支持單繼承,在應(yīng)對(duì)較復(fù)雜的業(yè)務(wù)邏輯中,單繼承就顯得捉襟見肘了。
trait的使用場(chǎng)景
如以下應(yīng)用場(chǎng)景:
class Person {
public function eat() {
echo "我是人,我能吃飯<br />";
}
}
class GuoJing extends Person {
public function kungfu() {
echo "降龍十八掌!<br />";
}
}
class XiaoFeng extends Person {
public function kungfu() {
echo "降龍十八掌!<br />";
}
}

蕭峰
Guojing 類 與 XiaoFeng 類都繼承于Person,都有共同的 Kungfu 方法,顯然,我們不能將這個(gè) Kungfu 方法寫到 Person 類,不然隨便一個(gè)路人甲繼承了 Person 類,就擁有了 Kungfu 技能。
用Trait就能解決此問題:
<?php
trait Tool {
public function kungfu() {
echo "降龍十八掌!<br />";
}
}
class Person {
public function eat() {
echo "我是人,我能吃飯<br />";
}
}
class GuoJing extends Person {
use Tool;
}
class XiaoFeng extends Person {
use Tool;
}
$guojing = new GuoJing();
$xiaofeng = new XiaoFeng();
$guojing->kungfu();
$xiaofeng->kungfu();
結(jié)果如下:
降龍十八掌!
降龍十八掌!
方法/屬性的重寫
如果Trait類、基類和本類中的方法或?qū)傩酝?,最終會(huì)以哪個(gè)為準(zhǔn)?
<?php
trait Tool {
public function kungfu() {
echo "降龍十八掌!<br />";
}
}
class Person {
public function eat() {
echo "我是人,我能吃飯<br />";
}
public function kungfu() {
echo "不是每個(gè)人都會(huì)功夫<br />";
}
}
class GuoJing extends Person {
use Tool;
public function kungfu() {
echo "除了降龍十八掌,我還懂九陰真經(jīng)!<br />";
}
}
class XiaoFeng extends Person {
use Tool;
}
$guojing = new GuoJing();
$guojing->kungfu();
結(jié)果:
除了降龍十八掌,我還懂九陰真經(jīng)!
注釋本類的 kungfu 方法,得出的結(jié)果是:
降龍十八掌!
當(dāng)方法或?qū)傩酝麜r(shí),當(dāng)前類中的方法會(huì)覆蓋 trait的 方法,而 trait 的方法又覆蓋了基類中的方法。
組合多個(gè)trait
多個(gè)trait有同名的方法/屬性時(shí),會(huì)報(bào)錯(cuò):
<?php
trait Tool {
public function kungfu() {
echo "降龍十八掌!<br />";
}
}
trait Skill {
public function kungfu() {
echo "渾厚的內(nèi)力修為<br />";
}
}
class GuoJing {
use Tool, Skill;
}
$guojing = new GuoJing();
$guojing->kungfu();
Fatal error: Trait method kungfu has not been applied, because there are collisions with other trait methods on GuoJing
解決方式:使用insteadof和as來解決沖突
insteadof: 使用某個(gè)方法替代另一個(gè)
as: 給方法取別名
<?php
trait Tool {
public function kungfu() {
echo "降龍十八掌!<br />";
}
}
trait Skill {
public function kungfu() {
echo "渾厚的內(nèi)力修為<br />";
}
}
class XiaoFeng {
use Tool, Skill {
Skill::kungfu insteadof Tool;
Skill::kungfu as ability;
}
}
$xiaofeng = new XiaoFeng();
$xiaofeng->ability();
渾厚的內(nèi)力修為
trait方法的訪問控制
as關(guān)鍵詞可以修改方法的訪問控制
<?php
trait Tool {
public function kungfu() {
echo "降龍十八掌!<br />";
}
}
class XiaoFeng {
use Tool {
Tool::kungfu as protected ability; // 修改方法的訪問控制并起別名
}
}
$xiaofeng = new XiaoFeng();
$xiaofeng->ability();
報(bào)錯(cuò):
Fatal error: Uncaught Error: Call to protected method XiaoFeng::ability() from context
Trait組合
Trait也能組合Trait,同時(shí),Trait中支持抽象方法、靜態(tài)屬性、靜態(tài)方法。
<?php
trait Tool {
public function kungfu() {
echo "降龍十八掌!<br />";
}
}
trait Feature{
use Tool;
abstract public function dream();
public static function character() {
echo "磊落豪雄 <br />";
}
}
class XiaoFeng {
use Feature;
public function dream() {
echo "弄清楚:我是誰? <br />";
}
}
$xiaofeng = new XiaoFeng();
$xiaofeng->kungfu();
XiaoFeng::character();
$xiaofeng->dream();
結(jié)果:
降龍十八掌!
磊落豪雄
弄清楚:我是誰?