歡迎您光臨本站 註冊首頁

PHP V5.3 中的新特性,第 1 部分: 對象介面的變化

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  
PHP V5.3 計劃在 2008 年底發行,這個版本包含了大量在過去一直處於計劃階段的新特性。PHP V5.3 在最初被譽為 “只缺少原生 Unicode 支持的 PHP V6”,現在它已經是 PHP V5 系列的全面升級。PHP V5.3 添加了新特性,並且對功能進行調試、修復與平台有關的問題、刪除不會在未來的 PHP 版本中出現的舊特性,為開發人員在未來使用 PHP V6 做好準備。在 “PHP V5.3 中的新特性” 系列文章中,我們將查看 V5.3 帶來的新特性,了解它們的使用以及如何將其應用到 Web 應用程序中。

PHP V5 和面向對象編程

與 PHP V4 提供的特性相比,2004 年發布的 PHP V5 在面向對象編程(OOP)和設計方面向前邁出了很大的一步。它提供了一些必要的改進,例如類可見性、合適的構造函數和解構函數、輸入提示和類反射(class-reflection)API。它為在 PHP 中進行高級的面向對象編程敞開了大門,並允許實現更加簡單的設計模式,以及更好的設計類和 API。

PHP V5.3 在 OOP 方面提供了大量漸進式補充。這些改進一直集中在語法補充和性能改進方面。首先,我們將查看靜態方法和成員方面的新特性。





改進靜態方法和成員處理

PHP V5 中的一個有用補充就是能夠將一個方法或類成員指定為靜態的(PHP V4 確實支持對方法和類成員的靜態訪問,但是不能夠將方法或成員指定為專門用於靜態訪問)。靜態訪問特別適合實現單一設計模式,在這種模式中只存在一個類實例。

PHP V5.3 提供一些特性來增強對類的靜態成員和方法的支持。我們將查看最近添加的一種魔術方法:__callStatic()。

_callStatic() 魔術方法

PHP V5 提供了一些可用於類內部的特別定義的方法,稱為魔術方法。當在類內部定義時,這些方法可以提供特殊的功能,並支持重載(允許一種方法接受不同類型的參數)和多態(允許不同數據類型使用相同的介面)。它們還允許通過 PHP 輕鬆地使用不同類型的 OOP 編程方法和設計模式。

在 PHP V5.3 中,添加了一種新的魔術方法:__callStatic()。它的工作方式類似於 __call() 魔術方法,後者的設計意圖是處理那些沒有在類中定義或對類不可見的方法的調用。然而,__callStatic() 是為了處理靜態方法調用,這使我們能夠更好地設計方法重載。下面給出了一個使用該方法的示例。


清單 1. 使用 __callStatic() 和 __call() 的示例
				   class Foo   {       public static function __callStatic(           $name,           $args           )       {           echo "Called method $name statically";       }         public function __call(           $name,           $args           )       {           echo "Called method $name";       }   }     Foo::dog();       // outputs "Called method dog statically"   $foo = new Foo;   $foo->dog();      // outputs "Called method dog"   

需要注意,PHP 確實加強了對 __callStatic() 方法的定義;它必須是公共的,並且必須被聲明為靜態的。同樣,__call() 魔術方法必須被定義為公共的,所有其他魔術方法都必須如此。





動態的靜態調用

PHP 的一個優秀特性是可變變數。這表示可以使用某個變數的字元串值指定另一個變數的名稱。換句話說,可以執行與下面類似的操作。


清單 2. 可變變數
				  x = 'y';   $x = 'z';   echo $x;  // outputs 'y'   echo $x; //   outputs 'z'   

這也適用於函數,甚至是類方法,如下所示。


清單 3. 可變函數和類方法名
				   class Dog   {       public function bark()       {           echo "Woof!";       }   }     $class = 'Dog'   $action = 'bark';   $x = new $class(); // instantiates the class 'Dog'   $x->$action();     // outputs "Woof!"   

PHP V5.3 的一個新特性就是在進行靜態調用時,能夠使指定的類名成為一個變數。這提供了一些新的機會,如下所示。


清單 4. 可變的類命名
				   class Dog   {       public static function bark()       {            echo "Woof!";       }   }     $class = 'Dog';   $action = 'bark';   $class::$action();  //outputs "Woof!"   

這一補充完善了 PHP 的可變變數特性,允許將它們應用到涉及 PHP 的所有情形。

讓我們查看一個有關靜態方法和成員應用的更有用的增強:延遲靜態綁定(late static binding)。





延遲靜態綁定

在 V5.3 以前,PHP 存在的麻煩問題是如何處理靜態方法和成員。到目前為止,使用自身或 __CLASS__ 進行的靜態引用都是在定義函數的類作用域中解析的。問題在於,如果類進行了擴展並且調用來自新的子類,那麼解析將是錯誤的。PHP V5.3 添加了延遲靜態綁定來解決這個問題。為了更好地進行解釋,我們在下面將創建一個具有靜態方法的類。


清單 5. 使用靜態方法 test() 的 Foo 類
				   class Foo   {       protected static $name = 'Foo';         public static function test()       {           return self::$name;       }   }   

讓我們對這個類進行擴展。我們將在子類中重新定義成員 $name。


清單 6. 子類 Bar 擴展了父類 Foo
				   class Bar   {       protected static $name = 'Bar';   }   

我們在清單 7 中進行了靜態調用。


清單 7. 靜態方法調用 test()
				   echo Bar::test();   

該調用的輸出是字元串 Foo。這是因為在 test() 方法中進行的引用 self::$name 是在 Foo 類中完成的。這樣綁定的原因是:函數是在 Foo 類中定義的。

PHP V5.3 添加了關鍵字 static 以允許針對當前類進行引用。因此將修改上面的 Foo 類以在清單 8 中使用該關鍵字,我們將看到輸出的內容變成了 Bar。


清單 8. 使用 static 關鍵字
				   class Foo   {       protected static $name = 'Foo';         public static function test()       {           return static::$name;       }   }     class Bar   {       protected static $name = 'Bar';   }     echo Bar::test(); // outputs 'Bar'  

有關 static 關鍵字需要注意一點,它的工作方式與在非靜態上下文中的工作方式不同。這意味著普通的繼承規則沒有應用到靜態調用中。靜態關鍵字將僅僅嘗試在當前類中解析調用,而不是在定義函數的類中執行。這一點值得注意。

現在您已經了解了有關靜態方法和成員的增強,現在讓我們看一看 PHP V5 中新添的類,它們構成了非常有用的部分:標準 PHP 庫。





標準 PHP 庫

標準 PHP 庫(Standard PHP Library,SPL)是 PHP V5 中新增的介面和類的集合,旨在解決標準問題。這些問題包括實現可迭代的對象,使對象具有數組的行為或實現一個鏈接的列表。這些類和方法的優點是它們是原生的 PHP,這意味用 PHP 本身實現它們會獲得更快的速度。在很多情況下,這些類和方法還允許內部 PHP 函數直接使用這些對象,就像 Iterator 介面允許您使用 foreach 結構迭代對象一樣。

PHP V5.3 向 SPL 添加了更多的類。我們前面提到一個類就是在 SPL 類 SplDoublyLinkedList 中實現的雙重鏈接列表。它供其他兩個新 SPL 類使用:SplStack(實現一個棧)和 SplQueue(實現一個隊列)。

讓我們看一看如何使用 SplStack 類實現一個棧。


清單 9. 使用 SplStack
				  $stack = new SplStack();     // push a few new items on the stack   $stack->push('a');   $stack->push('b');   $stack->push('c');     // see how many items are on the stack   echo count($stack); // returns 3     // iterate over the items in the stack   foreach ( $stack as $item )       echo "[$item],";     // the above outputs: [c],[b],[a]    // pop an item off the stack   echo $stack->pop(); // returns 'c'     // now see how many items are on the stack   echo count($stack); // returns 2  

SqlQueue 也採取類似的方式,但是它像隊列那樣工作(先進先出;而不是像棧一樣最後一個項進棧,第一個項出棧)。此外,還存在堆實現(SplHeap),以及針對某些情況的特定隊列和堆實現(SplMinHeap、SplMaxHeap 和 SplPriorityQueue)。

另一個有用的補充是 SplFixedArray 類,顧名思義,這是一個固定大小的數組實現。然而,它的性能非常快 — 實際上它在基準測試中要比 PHP 內置數組實現快 10% 至 30%。造成這種速度優勢的原因是數組是固定大小的,而默認的 PHP 數組是可變大小的,並且不允許非數值型索引。清單 10 顯示了它的使用方法。


清單 10. SplFixedArray
				  $array = new SplFixedArray(3);   $array[0] = 'dog';   $array[1] = 'cat';   $array[2] = 'bird';   $a->setSize(4); // increase the size on the fly   $array[3] = 'mouse';   foreach ( $array as $value )       echo "[$value],";    Output:   [dog],[cat],[bird],[mouse]   

此外,添加了一些新的迭代器類:FilesystemIterator 和 GlobIterator。它們與 PHP 中的其他迭代器類使用相同的工作方式,但是它們分別針對不同的情況。

SPL 的另一個改變是現在的 PHP V5.3 通常啟用 SPL。在以前的 PHP V5 版本中,可以在編譯時禁用 SPL,但是 PHP V5.3 不能禁用 SPL。

SPL 中的新補充?? PHP 添加了一些有用的並且易於使用的功能,以及數據結構的實現,例如雙重鏈接列表、棧、堆和隊列。這些類可用於替換用戶空間實現,這將改進速度並更好地集成各種 PHP 函數和構造。

現在我們已經了解了 SPL 中的一些新內容,讓我們看一看 PHP V5.3 中的 OOP 如何通過循環垃圾收集獲得顯著的性能和內存使用改善。





循環垃圾收集

垃圾收集是 PHP 開發人員在性能方面遇到的一個問題。PHP 有一個非常簡單的垃圾收集器,它實際上將對不再位於內存範圍(scope)中的對象進行垃圾收集。垃圾收集的內部方式是使用一個引用計數器,因此當計數器達到 0 時(意味著對該對象的引用都不可用),對象將被當作垃圾收集並從內存中刪除。

這種方式工作得很好,但是如果一個對象使用父子關係引用另一個對象,那就會引發問題。在這種情況下,這些對象的引用計數器沒有被收集,因此這些對象使用的內存仍然屬於未引用的內存,並且直到完成請求后才能夠進行分配。下面看一下關於這種問題的例子。


清單 11. PHP V5.2 及之前版本不能恰當地對父子類關係進行垃圾收集
				  class Parent   {       public function __construct()       {           $this->child = new Child($this);       }   }     class Child   {       public function __construct(           Parent $parent           )       {           $this->parent = $parent;       }   }   

在這種情況下,每當創建 Parent 類的實例並且該實例隨後超出內存範圍時,內存不會被釋放,因此腳本在內存使用中不斷增加。有一些用戶空間解決方案可以解決這個問題。例如為父類創建一個解構函數將直接釋放子對象。這種解構器必須在解除父類引用之前進行調用。但是執行這些工作會使您的代碼也變得非常複雜。

在 PHP V5.3 中,垃圾收集器將檢測這些循環引用,並且能夠釋放它們所佔用的內存,因此在執行腳本時 PHP 內存使用情況將保持平穩。當 Parent 類的每個引用被刪除后,Parent 類中的 Child 類引用也將會被當作垃圾收集。





結束語

PHP 在支持面向對象編程方面經歷了長期的發展。PHP V4 時期的支持是比較弱的,但在 PHP V5 中得到顯著的改善,並且後續版本還會調整。現在,PHP V5.3 提供了一些令人興奮的改進,包括語法增強,例如新 __callStatic() 魔術方法、動態的靜態調用、延遲靜態綁定、靜態方法和成員支持。它為 SPL 添加了新的內容,包括雙重鏈接表、棧、堆和隊列的實現,使您獲得了一些常見的數據結構並且可以輕鬆使用它們。最後,期待已久的循環垃圾收集器是一個經過改進的垃圾收集器,它恰當地為這些循環實例釋放內存,解決了自引用類的內存和性能問題。所有這些特性使 PHP V5.3 成為一種更加強大的面向對象編程語言。(責任編輯:A6)



[火星人 ] PHP V5.3 中的新特性,第 1 部分: 對象介面的變化已經有597次圍觀

http://coctec.com/docs/linux/show-post-69029.html