php5.4新功能Traits介紹
1. traits
Traits是在5.4中新增的一個用於實現代碼重用的方法。
php是一種單一繼承的語言,我們無法像java一樣在一個class中extends多個基類來實現代碼重用,現在Traits能解決這一代碼重用的問題,它能讓開發人員在多個不同的class中實現代碼重用。
Traits和class在語義的定義上都是為了減少代碼的複雜性,避免多重繼承的問題。
Traits 和class相似,但是僅用於以統一和較細粒度的方式來提供一組功能,在Traits內部無法進行執行個體化,即不存在類似class的建構函式__construct()。Traits作為一個php傳統繼承的擴充並實現水平整合;因此,在應用程式的class中可以不再需要繼承。
1)如何使用
在類中用關鍵字'use' 來引用 Traits。多個Traits 用','隔開。
執行個體代碼如下:
<?phptrait ezcReflectionReturnInfo {function getReturnType() {}function getReturnDescription() {}}class ezcReflectionMethod extends ReflectionMethod {use ezcReflectionReturnInfo;/* ... */}class ezcReflectionFunction extends ReflectionFunction {use ezcReflectionReturnInfo;/* ... */}?>
2)優先順序
基類中的成員函數將被Traits中的函數覆蓋,當前類中的成員函數將覆蓋Traits中的函數。
<?phpclass Base { public function sayHello() { echo 'Hello '; }}trait SayWorld { public function sayHello() { parent::sayHello(); echo "World!\n"; }}class MyHelloWorld extends Base { use SayWorld;}class MyHelloWorldExt extends Base {use SayWorld;public function sayHello() { /** * 這裡是5.4中的新的改動,5.4之前的版本會提示: * PHP Fatal error: Cannot use string offset as an array * 5.4中改進為返回字串中的該索引號的字元 */$str = "Arvin";echo $str[0][0];// echo 'A'; }public function shortArray() {$array = ['first', 2, 3, 4];//5.4中的數組簡單文法echo $array[0];//5.4中的數組解引用取數組元素方法}}$o = new MyHelloWorld();$o->sayHello();$oe = new MyHelloWorldExt();$oe->sayHello();echo "\n";$oe->shortArray();
輸出:Hello World!Afirst
3)多Traits
多個Traits可以添加到一個class的聲明中,多個Traits之間用","隔開。
<?phptrait Hello { public function sayHello() { echo 'Hello '; }}trait World { public function sayWorld() { echo 'World'; }}class MyHelloWorld { use Hello, World;}$o = new MyHelloWorld();$o->sayHello();$o->sayWorld();?>
輸出結果:
Hello World
4)多Traits衝突
如果添加到同一個class的兩個Traits中有相同的函數名稱,且沒有明確的進行處理,將產生一個錯誤。
為瞭解決同一個類中兩個Tratis中的同名函數衝突,需要用insteadof操作符來選擇正確的函數。
因為方法的唯一性和排他性,'as'操作符允許用在衝突函數之後以解決內部衝突的問題。
<?phptrait A {public function smallTalk() {echo 'a';}public function bigTalk() {echo 'A';}}trait B {public function smallTalk() {echo 'b';}public function bigTalk() {echo 'B';}}class Talker {use A, B {B::smallTalk insteadof A;A::bigTalk insteadof B;}}class Aliased_Talker {use A, B {B::smallTalk insteadof A;A::bigTalk insteadof B;B::bigTalk as talk;}}?>
上面的例子中,Talker使用Traits A 和B,因此兩者中相同的函數名稱存在衝突。
alker中定義了smallTalk取自Traits B,bigTalk取自Traits A。
Aliased_Talker中通過使用as操作符來確保Traits B中的bigTalk通過別名talk來實現。
5)改變函數存取權限
我們可以使用as文法來改變Traits中函數的存取權限屬性。
<?phptrait HelloWorld {public function sayHello() {echo 'Hello World!';}}// Change visibility of sayHello,改變sayHello的存取權限。class MyClass1 {use HelloWorld { sayHello as protected; }}// Alias method with changed visibility// sayHello visibility not changed,設定別名myPrivateHello。class MyClass2 {use HelloWorld { sayHello as private myPrivateHello; }}?>
6)Traits組成新Traits
就像許多類一樣可以在類中使用Traits,Traits中一樣可以使用Traits。可以在一個Traits中定義一個或者多個Traits,這些Traits 可以作為部分或者全部成員被定義在其他Traits中。
<?phptrait Hello {public function sayHello() {echo 'Hello ';}}trait World {public function sayWorld() {echo 'World!';}}trait HelloWorld {use Hello, World;}class MyHelloWorld {use HelloWorld;}$o = new MyHelloWorld();$o->sayHello();$o->sayWorld();?>
以上常式會輸出:
Hello World!
7)抽象Trait成員
為了在類中強制實現某些方法,可以在Traits中使用抽象方法。
例如:
<?phptrait Hello { public function sayHelloWorld() { echo 'Hello '.$this->getWorld(); } abstract public function getWorld();}class MyHelloWorld { private $world; use Hello;public function __construct($world) {$this->world = $world;} public function getWorld() { return $this->world; }}/** * 這裡用到了5.4新功能 類執行個體化解引用操作 * (new class())->method(); */(new MyHelloWorld('Arvin'))->sayHelloWorld();?>該執行個體輸出:Hello Arvin
8)靜態Trait成員
在Traits中不能定義static 靜態變數,但是可以定義在Tratis的函數中。Tratis中同樣可以定義靜態函數。
<?phptrait Counter { public function inc() { static $c = 0;//靜態變數 $c += 1; echo "$c\n"; }/** * 靜態方法 */public static function doSomething() { echo 'Doing something'; }}class C1 { use Counter;}(new C1())->inc(); // echo 1C1::doSomething();?>輸出為:1Doing something
9) Traits 定義屬性
如果在一個trait中定義了一個屬性,則在引用該trait的類中不能定義同名的屬性,如果該類中定義有和trait中已定義屬性具有相同的名字和訪問可見度,則是一個E_STRICT 提示,否則拋出語法錯誤。
<?phptrait PropertiesTrait { public $x = 1;public $y = 2;}class PropertiesExample { use PropertiesTrait;public $x = 1;//public $y = 3;}$example = new PropertiesExample;echo $example->x, $example->y;?>輸出:12
在最後貼上php5.4.0部分新功能changelog:
Added short array syntax support ([1,2,3]), see UPGRADING guide for full details.Added binary numbers format (0b001010).Added support for Class::{expr}() syntax.Added support for Traits.//本文的主要內容Added closure $this support back.Added array dereferencing support.//數組解引用支援,上文中有執行個體Added callable typehint.Added indirect method call through array. #47160.Added DTrace support.//傳說DTrace是一個效能分析工具,可以跟蹤出函數調用點,返回點等資料Added class member access on instantiation (e.g. (new foo)->bar()) support.//類新執行個體解引用操作,上文中有執行個體
本文旨在拋磚引玉,希望大家一起繼續探究php5.4的新功能。^_^