物件導向程式設計來為大型軟體專案提供解決方案,尤其是多人合作的專案. 當原始碼成長到一萬行甚至更多的時候,每一個更動都可能導致不希望的副作用. 這種情況發生在模組間結成秘密聯盟的時候,就像第一次世界大戰前的歐洲。
//haohappy註:喻指模組間的關聯度過高,相互依賴性太強.更動一個模組導致其它模組也必須跟著更動。
想像一下,如果有一個用來處理登入的模組允許一個信用卡處理模組來分享它的資料庫連接. 當然出發點是好的,節省了進行另一個資料庫連接的支出.然而有時,登入處理模組改變了其中一個變數的名字,就可能割斷了兩者間的協議.導致信用卡模組的處理出錯,進而導致處理發票的模組出錯. 很快地,體系中所有無關的模組都可能由此出錯.
因此,我覺得有點戲劇性地,絕大多數程式設計師都對耦合和封裝心存感激. 耦合是兩個模組間依賴程度的量度. 耦合越少越好.我們希望能夠從已有的項目中抽走一個模組並在另一個新專案中使用.
我們也希望在某個模組內部大規模的更動而不用擔心對其他模組的影響. 封裝的原則可以提供這個解決方案.模組被看待成相對獨立,並且模組間的數據通信透過介面來進行.模組不透過彼此的變數名稱來窺探另一個模組,它們透過函數來禮貌地發送請求.
封裝是你可以在任何程式語言中使用的一個原則. 在PHP和許多面向過程的語言中,可以偷懶是很有誘惑的.沒有什麼可以阻止你通過模組來構建一個假想的WEB. 面向對象編程是使程序員不會違背封裝原則的一種方法.
在面向對象編程中,模組被組織成一個個物件. 這些物件擁有方法和屬性. 從抽象的角度來看,方法是一個物件的所做的動作,而屬性是物件的特性.從程式設計角度來看,方法就是函數而屬性是變數. 在一個理想化的面向對象體系中,每個部份都是一個對象. 體係由對象及對象間通過方法來形成的聯繫構成.
一個類定義了對象的屬性. 如果你在烘烤一組甜餅對象,那麼類別將會是甜餅機. 類別的屬性和方法是被呼叫的成員. 人們可以透過說出資料成員或方法成員來表達.
每種語言提供了不同的途徑來存取物件. PHP從C++中借用概念,提供一個資料型別用來在一個標識符下包含函數和變數。最初設計PHP的時候,甚至PHP3被開發出時,PHP並不打算提供開發超過10萬行程式碼的大型專案的能力。隨著PHP和Zend引擎的發展,開發大型專案變得有可能,但無論你的專案規模多大,用類別來書寫你的腳本將可以讓程式碼實作重複使用。這是一個好主意,特別當你願意與別人分享你的程式碼的時候。
有關對象的想法是計算機科學上最令人興奮的概念之一。開始很難掌握它,但我可以保證,一旦你掌握了它,用它的思維來思考將會非常自然。
PHP5 的物件模型
PHP5有一個單重繼承的,限制存取的,可以重載的物件模型. 本章稍後會詳細討論的」繼承」,包含類別間的父-子關係. 另外,PHP支援對屬性和方法的限制性存取. 你可以宣告成員為private,不允許外部類別存取. 最後,PHP允許一個子類別從它的父類別中重載成員.
PHP5的物件模型把物件看成與任何其它資料型別不同,透過引用來傳遞. PHP不要求你透過引用(reference)顯性傳遞和返回物件. 在本章的最後將會詳細闡述基於引用的物件模型. 它是PHP5中最重要的新特性.
有了更直接的物件模型,就擁有了附加的優勢: 效率提高, 佔用內存少,並且具有更大的靈活性.
在PHP的前幾個版本中,腳本默認複製對象.現在PHP5只移動句柄,需要更少的時間. 腳本執行效率的提升是由於避免了不必要的複製. 在對象體系帶來複雜性的同時,也帶來了執行效率上的收益. 同時,減少複製意味著佔用更少的內存,可以留出更多內存給其它操作,這也使效率提高.
Zand引擎2具有更大的靈活性. 一個令人高興的發展是允許析構--在對象銷毀之前執行一個類方法. 這對於利用內存也很有好處,讓PHP清楚知道什麼時候沒有物件的引用,把空出的記憶體分配到其它用途.
PHP5的記憶體管理
物件傳遞
PHP5使用了Zend引擎II,物件被儲存於獨立的結構Object Store中,而不像其它一般變數那樣儲存於Zval中(在PHP4中物件和一般變數一樣儲存於Zval)。在Zval中僅儲存物件的指標而非內容(value)。當我們複製一個物件或將一個物件當作參數傳遞給一個函數時,我們不需要複製資料。僅僅保持相同的物件指標並由另一個zval通知現在這個特定的物件所指向的Object Store。由於物件本身位於Object Store,我們對它所做的任何改變將影響到所有持有該物件指標的zval結構----表現在程式中就是目標物件的任何改變都會影響到來源物件。 。這使得PHP物件看起來就像總是透過引用(reference)來傳遞,因此PHP中物件預設為透過「引用」傳遞,你不再需要像在PHP4中那樣使用&來宣告。
垃圾回收機制
某些語言,最典型的如C,需要你明確地要求分配記憶體當你創建資料結構。一旦你分配到內存,就可以在變數中存儲資訊。同時你也需要在結束使用變量時釋放內存,這使機器可以空出內存給其它變量,避免耗光內存。
PHP可以自動進行記憶體管理,清除不再需要的物件。 PHP使用了引用計數(reference counting)這個單純的垃圾回收(garbage collection)機制。每個對象內含一個引用計數器,每個reference連接到對象,計數器加1。當reference離開生存空間或被設為NULL,計數器會減1。當某個物件的參考計數器為零時,PHP知道你將不再需要使用這個對象,釋放其所佔的記憶體空間。
例如:
<?php
class Person{}
function sendEmailTo(){}
$haohappy = new Person( );
// 建立一個新物件: 引用計數Reference count = 1
$haohappy2 = $haohappy;
// 透過引用複製: Reference count = 2
unset($haohappy);
// 刪除一個引用: Reference count = 1
sendEmailTo($haohappy2);
// 透過引用傳遞物件:
// 在函數執行期間:
// Reference count = 2
// 執行結束後:
// Reference count = 1
unset($haohappy2);
// 刪除引用: Reference count = 0 自動釋放記憶體空間
?>