PHP4改變了這個情況. 新的版本帶來了引用(reference)的概念, 它允許PHP的不同標識符指向內存中的同一個地址. 這意味著你可以使用兩個或更多的名稱來給同一個變量命名,就像例6.20那樣.
由於所有物件導向的構建基礎是由於這個物件模式重大的意義.當引用允許建立更多強大的物件導向應用程式, PHP對待物件和其它類型資料相同的做法帶給開發者極大的痛苦.就像任何PHP4的程式設計師將會告訴你的, 應用程序將會遭遇WTMA(Way Too Many Ampersands過多&)綜合症. 如果你想構建一個實際應用,你會感到極為痛苦,看看例6.21你就明白.
1 class MyFoo {
2 function MyFoo()
$this->me = &$this;
5 $this->值 = 5;
6 }
7
8 函數 setValue($val) $this->value = $val;
11 }
12
13 return $this->value;
16 }
17
18 函數 getValueFromMe() 190 return $this->me->value;
21 }
22 }
23
24 {
26 switch ($class_type) {
27 >28 $obj = new MyFoo();
29 休息中;
30 $obj = new MyBar();
32 休息中;
33 return $obj;
35 }
36
37 $global_obj = CreateObject ("foo");
38 $global_obj->setValue(7);
39
40 印上「值是」。 「n」;
讓我們一步步來討論. 首先,有一個MyFoo類.在構造函數裡,我們給$this->me一個引用,並設定
我們有其它三個成員函數: 一個設定this ->value的值;一個回傳this->value的值;另一個回傳this->value->me的值. 但是--$this不是相同的東西嗎? MyFoo::getValue()和MyFoo::getValueFromMe ()回傳的值不是一樣的嗎?
首先,我們呼叫CreateObject("foo"),這會回傳一個MyFoo型別的物件. 然後我們呼叫MyFoo::setValue(7). 最後,我們呼叫MyFoo: :getValue() 和MyFoo::getValueFromMe(), 期望得到回傳值7.
當然,如果我們在任何情況下都得到7, 以上這個例子將不是本書中最沒有意義的例子. 所以我相信你已經猜到—我們得不到兩個7這樣的結果.
但是我們將得到什麼結果,並且更重要地,為什麼呢?
我們將得到的結果分別是7和5. 至於為什麼—--有三個很好的理由.
首先,看構造函數. 當在構造函數內部,我們在this和this->me間建立引用. 換句話說,this和this->me是同個東西. 但是我們是在建構函數內. 當建構子結束,PHP要重新建立物件(new MyFoo的結果,第28行)分配給$obj. 因為物件沒有特殊化對待,就像其它任何資料型別,賦值X給Y意味著Y是X的一個副本. 也就是說,obj將是new MyFoo的一個副本,而new MyFoo是一個存在於構造函數的對象. Obj->me怎麼樣呢? 因為它是一個引用,它原封不動仍然指向原來的對象—this. Voila-obj和obj->me不再是同個東西了—改變其中一個另一個不變.
以上是第一條理由. 還有其它類似於第一條的理由. 奇蹟般地我們打算克服實例化物件這個問題(第28行). 一旦我們把CreateObject回傳的值賦給global_object,我們仍然要撞上相同的問題—global_object將變成回傳值的一個副本,並且再次地,global_object和global_object->me將不再相同. 這就是第二條理由.
但是,事實上我們還走不了那麼遠— 一旦CreateObject返回$obj,我們將返回$obj,我們將返回$obj,我們將返回$obj,我們將返回$obj,破壞引用(第34行) . 這就是第三條理由.
那麼,我們如何改正這些? 有兩個選擇. 一是在所有地方增加&符號,就像例6.22那樣(第24, 28, 31, 37行). 二.如果你幸運地使用上了PHP5,你可以忘了以上這一切,PHP5會自動為你考慮這些. 如果你想知道PHP5是如何考慮這些問題的,繼續閱讀下去.
Listing 6.22 WTMA syndrome in PHP 4 PHP4中的WTMA症候群
複製代碼
複製代碼複製代碼1 class MyFoo {
2 function MyFoo()
$this->me = &$this;
5 $this->值 = 2;
6 }
7
8 函數 setValue($val) $this->value = $val;
11 }
12
13 return $this->value;
16 }
17
18 函數 getValueFromMe() 190 return $this->me->value;
21 }
22 };
23
24 {
26 switch ($class_type) {
27 🎜>28 $obj =& new MyFoo() ;
29 休息中;
30 $obj =& new MyBar();
32 休息中;
33 return $obj;
35 }
36
37 $global_obj =& CreateObject $global_obj =& CreateObject¡("foo);
38 $global_obj->setValue(7);
39
40 印上「值是」。 「n」;
PHP5是第一個把物件看成與其它類型資料不同的PHP版本. 從使用者的角度看,這證明它非常明白的方式—在PHP5中,物件總是透過引用來傳遞,而其它類型資料(如integer,string,array)都是透過值來傳遞. 最顯著地,沒有必要再用&符號來表示透過引用來傳遞物件了.
物件導向程式設計廣泛利用了物件網路和物件間的複雜關係,這些都需要用到引用. 在PHP的前些版本中,需要顯示地指明引用. 因此, 現在默認用引用來移動對象,並且只有在明確要求復制時才復制對象,這樣比以前更好.
它是如何實現的呢?
在PHP5之前,所有值都存在一個名為zval(Zend Value)的特殊結構裡. 這些值可以存入簡單的值,如數字和字符串,或複雜的值如數組和對象. 當值傳給函數或從函數返回時,這些值會被複製,在內存的另一個地址建立一個帶有相同內容的結構.
在PHP5中,值仍存為zval結構中,但對象除外. 對象存在一個叫做Object Store的結構裡,並且每個對像有一個不同的ID. Zval中,不儲存對象本身,而是存對象的指針. 當複製一個持有物件的zval結構,例如我們把一個物件當成參數傳給某個函數,我們不再複製任何資料. 我們僅僅保持相同的物件指標並由另一個zval通知現在這個特定的物件指向的Object Store. 因為物件本身位於Object Store,我們對它所做的任何改變將影響到所有持有該物件指標的zval結構.這種附加的間接作用使PHP物件看起來就像總是透過引用來傳遞,用透明和有效率的方式.
使用PHP5,我們現在可以回到範例6.21,除去所有的&符號, 一切程式碼都仍然可以正常工作.當我們在構造函數(第4行)中持有一個引用時一個&符號都不用.
http://www.bkjia.com/PHPjc/316925.htmlwww.bkjia.comtruehttp: //www.bkjia.com/PHPjc/316925.htmlTechArticle/* ---------------------- -------------------------------------------------- ------- |=本文為Haohappy讀CorePHPProgramming |=中ClassesandObjects一章的筆記|=翻譯為主個人...