[TOC] #### 1. trait 的介紹 --- 眾所周知,PHP 是單繼承的語言,也就是 PHP 中的類只能繼承一個(gè)父類,無法同時(shí)從多個(gè)基類中繼承屬性和方法,于是 PHP 實(shí)現(xiàn)了一種代碼復(fù)用的方法,稱之為 trait,使開發(fā)人員可以在不同層次結(jié)構(gòu)內(nèi)獨(dú)立的類中復(fù)用屬性和方法 trait 不是接口也不是類,不可以被實(shí)例化也不可以被繼承,只是用來將公共代碼(屬性和方法)提供給其他類使用的 #### 2. trait 的基礎(chǔ)用法 --- trait 的成員:trait 的成員只能有屬性和方法,不能定義類常量 ``` // 定義一個(gè) trait trait Say { // 在 trait 中不能定義常量 // 報(bào)錯(cuò)提示:Traits cannot have constants // const PI = 3.14; // 錯(cuò)誤示例 // 屬性 public static $name = 'liang'; // 方法 public static function hello() { echo 'Hello World !'; } } class User { use Say; // 在類中引入 trait } // 測(cè)試輸出 echo User::$name; echo User::hello(); ``` #### 3. trait 的優(yōu)先級(jí) --- 類成員和 trait 成員同名,屬性和方法有不同的處理 如果是屬性同名,PHP 直接拋出致命錯(cuò)誤,方法同名則會(huì)有優(yōu)先級(jí)之分 優(yōu)先順序是來自當(dāng)前類的成員覆蓋了 trait 的方法,而 trait 則覆蓋了被繼承的方法 ``` 當(dāng)前類成員 > trait 成員 > 繼承的成員 ``` #### 4. trait 的 as 用法 --- ```php trait User { protected function hello() { echo 'user hello'; } } class Person { use User { # 起別名 hello as helloNewName; # 起別名并且修改方法的訪問控制 hello as public helloNewName; } } $o = new Person; $o->helloNewName(); // user hello ``` #### 5. 引入多個(gè) trait 時(shí)的成員同名問題 --- 引入多個(gè) trait 時(shí),如果存在成員同名,那么 PHP 會(huì)直接拋出致命錯(cuò)誤 為了解決多個(gè) trait 在同一個(gè)類中的命名沖突,需要使用 insteadof 操作符來明確指定使用沖突方法中的哪一個(gè) 也就是需要使用 insteadof 操作符指定使用哪個(gè) trait 中的成員 ```php trait User { public function hello() { echo 'user hello <br>'; } } trait Admin { public function hello() { echo 'admin hello <br>'; } } class Person { use User, Admin { // 指定 hello 方法應(yīng)用哪個(gè) trait 上的 Admin::hello insteadof User; // User 上的 hello 想要使用的話就定義個(gè)別名,不想使用可以不定義別名 User::hello as helloUser; } } $o = new Person; $o->hello(); $o->helloUser(); ```