PHP中trait的特性
轉(zhuǎn)載鏈接:https://www.jb51.net/article/105579.htm
1.trait簡介
1.1 特性
(1)優(yōu)先級:當前類中的方法 > trait中的方法 > 基類中的方法
(2)多個trait使用,分隔
(3)trait 沖突使用insteadof操作符號來指定使用沖突方法中的哪一個
(4)as操作符可以為方法設(shè)置別名,也可以修改trait中的方法的訪問控制
(5)其他trait也可以使用trait。
(6)Traits 可以被靜態(tài)成員靜態(tài)方法定義。
(7)在引用Trait時,使用了use關(guān)鍵字,use關(guān)鍵字也用來引用命名空間。兩者的區(qū)別在于,引用Trait時是在class內(nèi)部使用的。比如thinkphp5框架中use concern\ModelRelationQuery;
(8)Trait 定義了一個屬性后,類就不能定義同樣名稱的屬性(名字,值和訪問控制相同就沒問題),否則會產(chǎn)生 fatal error。
1.2 優(yōu)點
解決代碼復(fù)用,解決PHP單繼承的問題;
1.3 區(qū)別
trait和class的區(qū)別是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(); //靜態(tài)變量不會改變 都是22.使用場景
熟悉面向?qū)ο蟮亩贾?軟件開發(fā)中常用的代碼復(fù)用有繼承和多態(tài)兩種方式。在PHP中,只能實現(xiàn)單繼承。而Trait則避免了這點。下面通過簡單的額例子來進行對比說明。
現(xiàn)在有Publish.php和Answer.php這兩個類。要在其中添加LOG功能,記錄類內(nèi)部的動作。有以下幾種方案:
繼承
多態(tài)
Trait
2.1. 繼承
如圖:
代碼結(jié)構(gòu)如下:
// Log.php
// Publish.php
<?php Class Publish extends Log {}// Answer.php
<?php Class Answer extends Log {}可以看到繼承的確滿足了要求。但這卻違背了面向?qū)ο蟮脑瓌t。而發(fā)布(Publish)和回答(Answer)這樣的操作和日志(Log)之間的關(guān)系并不是子類與父類的關(guān)系。所以不推薦這樣使用。
2.2. 多態(tài)
如圖:
// 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.} }記錄日志的操作應(yīng)該都是一樣的,因此,發(fā)布(Publish)和回答(Answer)動作中的日志記錄實現(xiàn)也是一樣的。很明顯,這違背了DRY(Don’t Repeat Yourself)原則。所以是不推薦這樣實現(xiàn)的。
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();可以看到,我們在沒有增加代碼復(fù)雜的情況下,實現(xiàn)了代碼的復(fù)用。
2.4. 結(jié)論
繼承的方式雖然也能解決問題,但其思路違背了面向?qū)ο蟮脑瓌t,顯得很粗暴;多態(tài)方式也可行,但不符合軟件開發(fā)中的DRY原則,增加了維護成本。而Trait方式則避免了上述的不足之處,相對優(yōu)雅的實現(xiàn)了代碼的復(fù)用。
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的PHP中trait的特性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php把字符串转为utf-8
- 下一篇: PHP中用于精确计算的bcmath扩展