類別中的某些成員如何被其他類別使用呢?使用繼承的話,這繼承鏈也太長了,為了方便,php提供了程式碼重複使用技術trait。
1.定義:Trait
是為類似 PHP 的單一繼承語言
而準備的一種程式碼重複使用機制。 trait可以使得單一繼承語言擺脫
為了復用,而不得不繼承的尷尬處境,讓物件導向
變得更純粹。
2.基礎語法:
trait是類似class
的關鍵字。
<?php trait Eat{ public $a=10; //trait内允许有类的成员属性(包括静态属性),成员方法(包括静态方法) public static $b=666; //const c=3.14; //trait内不允许有常量 protected $e; //允许定义,但是实际不用 private $f; public function getA() { echo $this->a,"<br>"; } public static function getB() { echo self::$b,"<br>"; } } ?>
trait
是用來實現程式碼的複用的,不能被實例化也不可以被繼承(因為根本不是類別)。
<?php trait Eat{} // $a=new Eat;//报错 //calss A extends Eat{}//报错 ?>
3.trait的使用
trait只是一段程式碼的集合,使用時必須使用use
#來引用。
<?php trait Eat{ public $a=10; public static $b=666; //const c=3.14; public function getA() { echo $this->a,"<br>"; } public static function getB() { echo self::$b,"<br>"; } } class A{ use Eat; public function getC() { echo $this->a,"<br>"; } } $boy=new A(); $boy->getC(); $boy->getA(); $boy->getB(); ?>
一個類別可以使用多個trait。
<?php trait A1{ } trait A2{ } class People{ use A1,A2; } ?>
4.trait使用的問題
# a.如果同時引入的多個trait中有同名屬性,那麼會產生衝突。
<?php trait A1{ public $a=11; } trait A2{ public $a=22; } class A3{ use A1,A2;//不允许同名属性 public function geta(){ echo $this->a; } } $example=new A3(); ?>
b.如果同時引入的多個trait中有同名方法,那麼會產生衝突,有兩種方案解決如A3、A4。
<?php trait A1{ public $a=11; public function eat(){ echo "A1中eat()方法","<br>"; } } trait A2{ public $b=22; public function eat(){ echo "A2中eat()方法","<br>"; } } class A3{ use A1,A2{ A1::eat insteadOf A2; //A1中的eat替代A2中的eat } } class A4{ use A1,A2{ A1::eat insteadOf A2;//A1中的eat替代A2中的eat A2::eat as eat2; //A2中的eat取别名eat2 } } $example=new A3(); $example->eat(); $example=new A4(); $example->eat2(); ?>
c.同名覆蓋問題:如果類別中有與引入的trait同名成員,會有不同處理:
屬性:不允許重名,即類別中不允許定義與trait中同名的成員屬性(靜態屬性也是一樣)。
方法:類別覆寫trait。
d.繼承覆蓋問題:如果類別中在使用trait
的同時,也是繼承自父類,而trait中與父類中有同名方法,那麼trait
中將覆寫父類別同名方法;如果要存取父類別方法,可以在trait同名方法中使用parent
關鍵字存取父類別同名方法。
<?php trait Eat{ public function eat(){ echo 'Eat::eat'; } } class Human{ public function eat(){ echo 'Human::eat'; } } //子类继承父类同时使用trait class Man extends Human{ use Eat; } $m = new Man(); $m->eat(); ?>
e.trait自己不能訪問,只是用來給其他類別提供程式碼重複使用的,因此允許類別在使用trait時,使用更高的存取控制權:在as
之後,使用目標存取修飾限定符。
<?php trait Eat{ private function show(){ echo 'eat'; } } class Human{ use Eat{ show as public eshow; //注意:as是用来设定别名的,虽然没有同名show,但是系统认为show已经存在,所以必须别名,权限的更改的方法不是 //本尊 } } $h = new Human(); $h->eshow(); //eat ?>
f.trait中可以使用抽象方法
,使用類別必須實作對應抽象方法
:使用類別要麼為抽象類,要麼就必須實作抽象方法。
<?php trait Eat{ public function eat(); //抽象方法 } abstract class Human{ use Eat; //抽象类:可以不实现抽象方法 } class Animal{ use Eat; public function eat(){ //具体类:实现抽象方法 echo 'Animal::eat'; } } ?>#
以上是總是在重複,氣抖冷,trait何時才能站起來?的詳細內容。更多資訊請關注PHP中文網其他相關文章!