溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

php5.3后靜態(tài)綁定的示例分析

發(fā)布時間:2021-08-30 14:34:19 來源:億速云 閱讀:118 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(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

php5.3后靜態(tài)綁定的示例分析

由圖的繼承關(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é)到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(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)容。

AI