溫馨提示×

溫馨提示×

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

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

php5.3后靜態綁定的示例分析

發布時間:2021-08-30 14:34:19 來源:億速云 閱讀:141 作者:小新 欄目:開發技術

這篇文章給大家分享的是有關php5.3后靜態綁定的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

具體如下:

手冊原文:

自 PHP 5.3.0 起,PHP 增加了一個叫做后期靜態綁定的功能,用于在繼承范圍內引用靜態調用的類。

準確說,后期靜態綁定工作原理是存儲了在上一個"非轉發調用"(non-forwarding call)的類名。當進行靜態方法調用時,該類名即為明確指定的那個(通常在 :: 運算符左側部分);當進行非靜態方法調用時,即為該對象所屬的類。所謂的"轉發調用"(forwarding call)指的是通過以下幾種方式進行的靜態調用:self::,parent::,static:: 以及 forward_static_call()??捎?get_called_class() 函數來得到被調用的方法所在的類名,static:: 則指出了其范圍。

該功能從語言內部角度考慮被命名為"后期靜態綁定"。"后期綁定"的意思是說,static:: 不再被解析為定義當前方法所在的類,而是在實際運行時計算的。也可以稱之為"靜態綁定",因為它可以用于(但不限于)靜態方法的調用。

self:: 的限制

使用 self:: 或者 __CLASS__ 對當前類的靜態引用,取決于定義當前方法所在的類:

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

后期靜態綁定的用法 后期靜態綁定本想通過引入一個新的關鍵字表示運行時最初調用的類來繞過限制。簡單地說,這個關鍵字能夠讓你在上述例子中調用 test() 時引用的類是 B 而不是 A。最終決定不引入新的關鍵字,而是使用已經預留的 static 關鍵字。

Example #2 static:: 簡單用法

<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // 后期靜態綁定從這里開始
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test();
?>

以上例程會輸出:

B

Note: 在非靜態環境下,所調用的類即為該對象實例所屬的類。由于 $this-> 會在同一作用范圍內嘗試調用私有方法,而 static:: 則可能給出不同結果。另一個區別是 static:: 只能用于靜態屬性。

Example #3 非靜態環境下使用 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: 后期靜態綁定的解析會一直到取得一個完全解析了的靜態調用為止。另一方面,如果靜態調用使用 parent:: 或者 self:: 將轉發調用信息。

Example #4 轉發和非轉發調用

<?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后期靜態綁定功能解決在繼承范圍內引用靜態調用的類。

先看如下代碼:

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

很明顯,結果不是我們預期的,這是因為self::取決于定義時所在的類,而不是運行中的類。為了解決這個問題,你可能會在繼承類中重寫status()方法,更好的解決方案是PHP 5.3后添加了后期靜態綁定的功能。

代碼如下:

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::不在指向當前所在的類,實際上,它是在運行中計算的,強制獲取最終類的所有屬性。

因此,建議,以后不要再使用self::,使用static::

補充:

網友帖1

php的后期靜態綁定,怎么解釋?下面的這幅圖輸出是A,C,C

php5.3后靜態綁定的示例分析

由圖的繼承關系可知:C徹底包含了B和A。

在看答案結果以前,他細觀察發現,三個類里都有同一個名稱who()方法。
系統會用最后一個優先級最高,進一步的說,你幾乎沒法通過C去調用A、B內的who(),只能重改方法,比如添加個getBWho(){echo B::who();}
然后通過C::getBWho();來調用B內的who();

下面來看運行結果:

test只在B中出現,所以結果必然是test()中運行的三個結果:

第一個:靜態直接指名到姓的調用A內靜態函數,這沒有懸念,必然是A
第二個:parent::是調用上一級的父類,在此題中為A,A中又直接調用static:who();上面說過了,這個who()優先級最高的在C里面,無論在你ABC中哪里調用,只要是static::who()必然是最后定義的那個,覆蓋效應,如果想調用A里的必需指明A::who()或是通過去除static從作用域限制來實現。所以這個who()就是C中定義的who
第三個:self::who與第二個類似的問題,看樣該走B的,注意覆蓋效應,要想調用B內的who必須得B::who(),因為更高級的C已經重寫了這個方法,如果C中沒有who,肯定就是B,依次類推。所以必然還是調用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

網友帖2

(還是針對上面圖中的代碼)

手冊不是說得很清楚么

”后期綁定“的意思是說,static::不再被解析為定義當前方法所在的類,而是在實際運行時計算的。也可以稱之為”靜態綁定“,因為它可以用于(但不限于)靜態方法的調用。

#1說的有個小問題

【self::foo(); // 這個self實際上是C類。明白嗎? C::test() C繼承了B的test()方法】

不準確,self還是B類,但是本身沒有覆寫foo方法,所以就調用父類A的foo方法。

如果self實際是C類,那你試下self::foo();改成self::who();,應當打印C,但是打印B,這也正是self和static的區別。

<?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

網友帖3

A::foo(); //A指代A類,訪問A類的foo方法和who方法
parent::foo();//調用B類的父類——A的foo方法,并告訴foo方法最原始的調用者是C
self::foo(); //self指代定義該方法的類,即B,但是B沒有定義foo方法,它將原始的調用者C向上傳遞,
// 訪問父類的foo方法,最后訪問c的who方法;

所以這就回答了樓上的疑問:若是把self::foo(); 改成self::who(),因為self指代B,而B有who方法,所以結果是變成了B

靜態調用使用 parent:: 或者 self:: 將轉發原始調用信息。

感謝各位的閱讀!關于“php5.3后靜態綁定的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女