您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)php5.3后靜態(tài)綁定的示例分析的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
具體如下:
手冊原文:
自 PHP 5.3.0 起,PHP 增加了一個叫做后期靜態(tài)綁定的功能,用于在繼承范圍內(nèi)引用靜態(tài)調(diào)用的類。
準(zhǔn)確說,后期靜態(tài)綁定工作原理是存儲了在上一個"非轉(zhuǎn)發(fā)調(diào)用"(non-forwarding call)的類名。當(dāng)進行靜態(tài)方法調(diào)用時,該類名即為明確指定的那個(通常在 :: 運算符左側(cè)部分);當(dāng)進行非靜態(tài)方法調(diào)用時,即為該對象所屬的類。所謂的"轉(zhuǎn)發(fā)調(diào)用"(forwarding call)指的是通過以下幾種方式進行的靜態(tài)調(diào)用:self::,parent::,static:: 以及 forward_static_call()??捎?get_called_class() 函數(shù)來得到被調(diào)用的方法所在的類名,static:: 則指出了其范圍。
該功能從語言內(nèi)部角度考慮被命名為"后期靜態(tài)綁定"。"后期綁定"的意思是說,static:: 不再被解析為定義當(dāng)前方法所在的類,而是在實際運行時計算的。也可以稱之為"靜態(tài)綁定",因為它可以用于(但不限于)靜態(tài)方法的調(diào)用。
self:: 的限制
使用 self:: 或者 __CLASS__ 對當(dāng)前類的靜態(tài)引用,取決于定義當(dāng)前方法所在的類:
Example #1 self:: 用法
<?php class A { public static function who() { echo __CLASS__; } public static function test() { self::who(); } } class B extends A { public static function who() { echo __CLASS__; } } B::test(); ?>
以上例程會輸出:
A
后期靜態(tài)綁定的用法 后期靜態(tài)綁定本想通過引入一個新的關(guān)鍵字表示運行時最初調(diào)用的類來繞過限制。簡單地說,這個關(guān)鍵字能夠讓你在上述例子中調(diào)用 test() 時引用的類是 B 而不是 A。最終決定不引入新的關(guān)鍵字,而是使用已經(jīng)預(yù)留的 static 關(guān)鍵字。
Example #2 static:: 簡單用法
<?php class A { public static function who() { echo __CLASS__; } public static function test() { static::who(); // 后期靜態(tài)綁定從這里開始 } } class B extends A { public static function who() { echo __CLASS__; } } B::test(); ?>
以上例程會輸出:
B
Note: 在非靜態(tài)環(huán)境下,所調(diào)用的類即為該對象實例所屬的類。由于 $this-> 會在同一作用范圍內(nèi)嘗試調(diào)用私有方法,而 static:: 則可能給出不同結(jié)果。另一個區(qū)別是 static:: 只能用于靜態(tài)屬性。
Example #3 非靜態(tài)環(huán)境下使用 static::
<?php class A { private function foo() { echo "success!\n"; } public function test() { $this->foo(); static::foo(); } } class B extends A { /* foo() will be copied to B, hence its scope will still be A and * the call be successful */ } class C extends A { private function foo() { /* original method is replaced; the scope of the new one is C */ } } $b = new B(); $b->test(); $c = new C(); $c->test(); //fails ?>
以上例程會輸出:
success!
success!
success!
Fatal error: Call to private method C::foo() from context 'A' in /tmp/test.php on line 9
Note: 后期靜態(tài)綁定的解析會一直到取得一個完全解析了的靜態(tài)調(diào)用為止。另一方面,如果靜態(tài)調(diào)用使用 parent:: 或者 self:: 將轉(zhuǎn)發(fā)調(diào)用信息。
Example #4 轉(zhuǎn)發(fā)和非轉(zhuǎn)發(fā)調(diào)用
<?php class A { public static function foo() { static::who(); } public static function who() { echo __CLASS__."\n"; } } class B extends A { public static function test() { A::foo(); parent::foo(); self::foo(); } public static function who() { echo __CLASS__."\n"; } } class C extends B { public static function who() { echo __CLASS__."\n"; } } C::test(); ?>
以上例程會輸出:
A
C
C
下面示例分析了基于PHP后期靜態(tài)綁定功能解決在繼承范圍內(nèi)引用靜態(tài)調(diào)用的類。
先看如下代碼:
class Person { public static function status() { self::getStatus(); } protected static function getStatus() { echo "Person is alive"; } } class Deceased extends Person { protected static function getStatus() { echo "Person is deceased"; } } Deceased::status(); //Person is alive
很明顯,結(jié)果不是我們預(yù)期的,這是因為self::取決于定義時所在的類,而不是運行中的類。為了解決這個問題,你可能會在繼承類中重寫status()方法,更好的解決方案是PHP 5.3后添加了后期靜態(tài)綁定的功能。
代碼如下:
class Person { public static function status() { static::getStatus(); } protected static function getStatus() { echo "Person is alive"; } } class Deceased extends Person { protected static function getStatus() { echo "Person is deceased"; } } Deceased::status(); //Person is deceased
可見,static::不在指向當(dāng)前所在的類,實際上,它是在運行中計算的,強制獲取最終類的所有屬性。
因此,建議,以后不要再使用self::,使用static::
補充:
網(wǎng)友帖1
php的后期靜態(tài)綁定,怎么解釋?下面的這幅圖輸出是A,C,C
由圖的繼承關(guān)系可知:C徹底包含了B和A。
在看答案結(jié)果以前,他細(xì)觀察發(fā)現(xiàn),三個類里都有同一個名稱who()方法。
系統(tǒng)會用最后一個優(yōu)先級最高,進一步的說,你幾乎沒法通過C去調(diào)用A、B內(nèi)的who(),只能重改方法,比如添加個getBWho(){echo B::who();}
然后通過C::getBWho();來調(diào)用B內(nèi)的who();
下面來看運行結(jié)果:
test只在B中出現(xiàn),所以結(jié)果必然是test()中運行的三個結(jié)果:
第一個:靜態(tài)直接指名到姓的調(diào)用A內(nèi)靜態(tài)函數(shù),這沒有懸念,必然是A
第二個:parent::是調(diào)用上一級的父類,在此題中為A,A中又直接調(diào)用static:who();上面說過了,這個who()優(yōu)先級最高的在C里面,無論在你ABC中哪里調(diào)用,只要是static::who()必然是最后定義的那個,覆蓋效應(yīng),如果想調(diào)用A里的必需指明A::who()或是通過去除static從作用域限制來實現(xiàn)。所以這個who()就是C中定義的who
第三個:self::who與第二個類似的問題,看樣該走B的,注意覆蓋效應(yīng),要想調(diào)用B內(nèi)的who必須得B::who(),因為更高級的C已經(jīng)重寫了這個方法,如果C中沒有who,肯定就是B,依次類推。所以必然還是調(diào)用C中的who;
所以答案為:ACC
代碼如下:
<?php class A { public static function foo() { static::who(); } public static function who() { echo __CLASS__."\n"; } } class B extends A { public static function test() { A::foo(); parent::foo(); self::foo(); } public static function who() { echo __CLASS__."\n"; } } class C extends B { //public static function who() { // echo __CLASS__."\n"; //} } C::test(); ?>
輸出為:A B B
網(wǎng)友帖2
(還是針對上面圖中的代碼)
手冊不是說得很清楚么
”后期綁定“的意思是說,static::不再被解析為定義當(dāng)前方法所在的類,而是在實際運行時計算的。也可以稱之為”靜態(tài)綁定“,因為它可以用于(但不限于)靜態(tài)方法的調(diào)用。
#1說的有個小問題
【self::foo(); // 這個self實際上是C類。明白嗎? C::test() C繼承了B的test()方法】
不準(zhǔn)確,self還是B類,但是本身沒有覆寫foo方法,所以就調(diào)用父類A的foo方法。
如果self實際是C類,那你試下self::foo();改成self::who();,應(yīng)當(dāng)打印C,但是打印B,這也正是self和static的區(qū)別。
<?php class A { public static function foo() { static::who(); } public static function who() { echo __CLASS__."\n"; } } class B extends A { public static function test() { A::foo(); parent::foo(); self::who(); } public static function who() { echo __CLASS__."\n"; } } class C extends B { public static function who() { echo __CLASS__."\n"; } } C::test(); ?>
輸出為:A C B
網(wǎng)友帖3
A::foo(); //A指代A類,訪問A類的foo方法和who方法 parent::foo();//調(diào)用B類的父類——A的foo方法,并告訴foo方法最原始的調(diào)用者是C self::foo(); //self指代定義該方法的類,即B,但是B沒有定義foo方法,它將原始的調(diào)用者C向上傳遞, // 訪問父類的foo方法,最后訪問c的who方法;
所以這就回答了樓上的疑問:若是把self::foo(); 改成self::who(),因為self指代B,而B有who方法,所以結(jié)果是變成了B
靜態(tài)調(diào)用使用 parent:: 或者 self:: 將轉(zhuǎn)發(fā)原始調(diào)用信息。
感謝各位的閱讀!關(guān)于“php5.3后靜態(tài)綁定的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。