除了限制訪問,訪問方式也決定哪個方法將被子類呼叫或哪個屬性將被子類訪問. 函式呼叫與函式本身的關聯,以及成員訪問與變數記憶體位址間的關係,稱為繫結。
在計算機語言中有兩種主要的繫結方式—靜態繫結和動態繫結。靜態繫結發生於資料結構和資料結構間,程式執行之前. 靜態繫結發生於編譯期, 因此不能利用任何執行期的資訊。它針對函式呼叫與函式的主體,或變數與記憶體中的區塊。因為php是一種動態語言,它不使用靜態繫結。但是可以模擬靜態繫結。
動態繫結則針對執行期產生的訪問請求,只用到執行期的可用資訊。在物件導向的**中,動態繫結意味著決定哪個方法被呼叫或哪個屬性被訪問,將基於這個類本身而不基於訪問範圍。
public和protected成員的動作類似於php的前幾個版本中函式的動作,使用動態繫結。這意味著如果乙個方法訪問乙個在子類中被覆寫的類成員,並是乙個子類的例項,子類的成員將被訪問(而不是訪問父類中的成員)。
看例子6.10. 這段**輸出」 hey! i am son.」 因為當php呼叫getsalutation, 是乙個son的例項,是將father中的salutation覆寫而來. 如果salutation是public的,php將產生相同的結果. 覆寫方法的操作很類似。在son中,對於identify的呼叫繫結到那個方法。
即使在子類中訪問方式被從protected削弱成public, 動態繫結仍然會發生. 按照訪問方式使用的原則,增強對於類成員的訪問限制是不可能的,所以把訪問方式從public改變成protected不可能進行。
listing 6.10 dynamic binding 動態繫結
class father
protected function identify()
}; class son extends father
}; $obj = new son();rfyoyckcl
$obj->getsalutation(); //輸出hey! i am son.
?> //注: 在子類中沒有覆寫getsalutation(),但實際上仍然存在乙個getsalutation().這個類中的$salutation和identify()
//與son子類的例項中的getsalutation方法動態繫結,所以呼叫son的例項的getsalutation()方法,
//將呼叫son類中的成員salutation及identify(),而不是父類中的成員salutation及identify().
private成員只存在於它們所在的類內部. 不像public和protected成員那樣,php模擬靜態繫結. 看例子6.11。它輸出」hello there! i am father.」,儘管子類覆寫了salutation的值,指令碼將this->salutation和當前類father繫結. 類似的原則應用於private方法identify()。
listing 6.11 binding and private members
class father
private function identify() }
class son extends father }
$obj = new son();
$obj->getsalutation(); //輸出hello there! i am father.
?> 動態繫結的好處是允許繼承類來改變父類的行為,同時可以保持父類的介面和功能,看例子6.12. 由於使用了動態繫結,在deleteuser中被呼叫的isauthorized的version 可以由物件的型別來確定。如果是乙個普通的user,php呼叫user::isauthorized會返回false.如果是乙個authorizeduser的例項,php呼叫authorizeduser::isauthorized,將允許deleteuser順利執行。
//haohappy注:用一句話說清楚,就是物件型別與方法,屬性繫結. 呼叫乙個父類與子類中都存在的方法或訪問乙個屬性時,會先判斷例項屬於哪種物件型別,再呼叫相應的類中的方法和屬性.
listing 6.12 動態繫結的好處
class user //使用者
public function getname() //獲得名字
public function deleteuser($username) //刪除使用者
//delete the user
print("user deleted.
n");
} }
class authorizeduser extends user //認證使用者 }
$user = new user;
$admin = new authorizeduser;
//not authorized
$user->deleteuser("zeev");
//authorized
$admin->deletrfyoyckcleuser("zeev");
?>
為什麼private的類成員模擬靜態繫結? 為了程式設計客棧回答這個問題, 你需要回憶一下為什麼需要有private成員.什麼時候用它們來代替protected成員是有意義的?
private成員只有當你不想讓子類繼承改變或特殊化父類的行為時才用到,這種情況比你想像的要少, 通常來說,乙個好的物件分層結構應當允許絕大程式設計客棧多數功能被子類特殊化,改進,或改變—這是物件導向程式設計的基礎之一。一定的情況下需要private方法或變數,例如當你確信你不想允許子類改變父類中的某個特定的部份。
本文標題: php 5.0物件模型深度探索之繫結
本文位址:
PHP 5 0物件模型深度探索之屬性和方法
乙個物件例項的屬性是變數,就像php的其他變數一樣。但是你必須使用 運算子來引用它們。不需要在屬性前使用美元符 可以聯用 如果乙個物件的屬性包含了乙個物件,你可以使用兩個 運算子來得到內部物件的屬性.你甚至可以用雙重引用的字串來放置這些表示式.下面的例子中,物件house中的屬性room包含了一組r...
PHP 5 0物件模型深度探索之構造和析構
如果你在乙個類中宣告乙個函式,命名為 construct,這個函式將被當成是乙個建構函式並在建立乙個物件例項時被執行。清楚地說,是兩個下劃線。就像其它任何函式一樣,建構函式可能有引數或者預設值.你可以定義乙個類來建立乙個物件並將其屬性全放在乙個語句 statement 中。你也可以定義乙個名為 de...
PHP5 0物件模型深度探索之類的靜態成員
類的靜態成員與一般的類成員不同 靜態成員與物件的例項無關,只與類本身有關。他們用來實現類要封裝的功能和資料,但不包括特定物件的功能和資料,靜態成員包括靜態方法和靜態屬性。靜態屬性包含在類中要封裝的資料,可以由所有類的例項共享。實際上,除了屬於乙個固定的類並限制訪問方式外,類的靜態屬性非常類似於函式的...