PHP中trait的特性
轉載鏈接:https://www.jb51.net/article/105579.htm
1.trait簡介
1.1 特性
(1)優先級:當前類中的方法 > trait中的方法 > 基類中的方法
(2)多個trait使用,分隔
(3)trait 沖突使用insteadof操作符號來指定使用沖突方法中的哪一個
(4)as操作符可以為方法設置別名,也可以修改trait中的方法的訪問控制
(5)其他trait也可以使用trait。
(6)Traits 可以被靜態成員靜態方法定義。
(7)在引用Trait時,使用了use關鍵字,use關鍵字也用來引用命名空間。兩者的區別在于,引用Trait時是在class內部使用的。比如thinkphp5框架中use concern\ModelRelationQuery;
(8)Trait 定義了一個屬性后,類就不能定義同樣名稱的屬性(名字,值和訪問控制相同就沒問題),否則會產生 fatal error。
1.2 優點
解決代碼復用,解決PHP單繼承的問題;
1.3 區別
trait和class的區別是trait不能被實例化
1.4 代碼
<?phpclass Base{ // public function sayHello(){ // echo "hello"; // } }trait Mood{public $a =1;public function sayMood(){echo "!";} }trait Sayworld{public function sayHello(){// parent::sayHello();echo "world";}abstract public function getWorld();public static function doSomething(){echo "static function";} }class MyHelloWorld extends Base{use Sayworld,Mood{sayHello as public;}public $a =1 ; //=2值不同就會fatal errorpublic function getWorld(){return "getWorld";} // public function sayHello() // { parent::sayHello(); // echo "MyHelloWorld"; // } }$o = new MyHelloWorld(); $o->sayHello(); $o->sayMood(); $o::doSomething(); trait Man{use Sayworld;public function eat(){echo "man word";}public function talk(){echo "Chinese";}public function inc(){static $i=1;$i++;echo $i;}}trait Woman{public function eat(){echo "woman home";}public function talk(){echo "English";} }class Person{use Man,Woman{Woman::eat insteadof Man;Man::talk insteadof Woman;Woman::talk as talks;}public function getWorld(){// TODO: Implement getWorld() method.}} class Animals{use Man;public function getWorld(){// TODO: Implement getWorld() method.} } $person = new Person(); //$person->eat(); //$person->talks(); //$person->sayHello(); $person->inc(); (new Animals())->inc(); //靜態變量不會改變 都是22.使用場景
熟悉面向對象的都知道,軟件開發中常用的代碼復用有繼承和多態兩種方式。在PHP中,只能實現單繼承。而Trait則避免了這點。下面通過簡單的額例子來進行對比說明。
現在有Publish.php和Answer.php這兩個類。要在其中添加LOG功能,記錄類內部的動作。有以下幾種方案:
繼承
多態
Trait
2.1. 繼承
如圖:
代碼結構如下:
// Log.php
// Publish.php
<?php Class Publish extends Log {}// Answer.php
<?php Class Answer extends Log {}可以看到繼承的確滿足了要求。但這卻違背了面向對象的原則。而發布(Publish)和回答(Answer)這樣的操作和日志(Log)之間的關系并不是子類與父類的關系。所以不推薦這樣使用。
2.2. 多態
如圖:
// Log.php
// Publish.php
<?php Class Publish implements Log {public function startLog(){// TODO: Implement startLog() method.}public function endLog(){// TODO: Implement endLog() method.} }// Answer.php
<?php Class Answer implements Log {public function startLog(){// TODO: Implement startLog() method.}public function endLog(){// TODO: Implement endLog() method.} }記錄日志的操作應該都是一樣的,因此,發布(Publish)和回答(Answer)動作中的日志記錄實現也是一樣的。很明顯,這違背了DRY(Don’t Repeat Yourself)原則。所以是不推薦這樣實現的。
2.3. Trait
如圖:
// Log.php
// Publish.php
<?php class Publish {use Log; } $publish = new Publish(); $publish->startLog(); $publish->endLog();// Answer.php
<?php class Answer {use Log; } $answer = new Answer(); $answer->startLog(); $answer->endLog();可以看到,我們在沒有增加代碼復雜的情況下,實現了代碼的復用。
2.4. 結論
繼承的方式雖然也能解決問題,但其思路違背了面向對象的原則,顯得很粗暴;多態方式也可行,但不符合軟件開發中的DRY原則,增加了維護成本。而Trait方式則避免了上述的不足之處,相對優雅的實現了代碼的復用。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的PHP中trait的特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php把字符串转为utf-8
- 下一篇: PHP中用于精确计算的bcmath扩展