2013-12-17 93 views
0

我在PHP中遇到了一些似乎很奇怪的東西。我試圖從一個非靜態方法訪問一個靜態屬性。我需要使用static關鍵字來訪問此屬性,因爲它可以在每個子類中具有不同的值。從PHP中的非靜態方法訪問不正確的靜態屬性

但是,不是從預期的類中訪問屬性,而是從調用類訪問屬性。這對我來說似乎是一個錯誤,但如果不是,我想知道是否有人可以向我解釋這種行爲,並解釋我如何訪問這個靜態屬性。

在這裏,我的期望是,靜態屬性$爲什麼會從類B.採取我困惑,爲什麼反而會從A類採取

<?php 

error_reporting(E_ALL & ~E_STRICT); 

class A 
{ 
    public static $why = "Really don't want this value. Bug?"; 
    public function callB() 
    { 
     $B = new B; 
     $B::getWhy(); // PHP Bug? 
     $B->getWhy(); 
     $B::getWhyStatic(); 
     $B::getWhyStaticSelf(); 
    } 
} 

class Base { 

    protected static $why = "Don't want this value"; 

    public static function getWhyStatic() 
    { 
     echo static::$why . "<BR>\n";  
    } 

    public static function getWhyStaticSelf() 
    { 
     echo self::$why . "<BR>\n";  
    } 

    public function getWhy() 
    { 
     echo static::$why . "<BR>\n"; 
    } 
} 

class B extends Base 
{ 
    protected static $why = "Want this value?"; 
} 

$A = new A; 
$A->callB(); 
+0

你需要與你的問題更明確,比如,你希望哪個屬性來訪問和訪問呢? – ollieread

+0

已經添加了一些額外的說明。將不勝感激取消投票。 –

+0

刪除投票,看到我編輯的答案在下面,將'$ B :: bah()'改爲'$ B-> bah()'應該修復它 – ollieread

回答

2

$B::bah();$B->bah();,爲bah不是一個靜態函數。

+0

是的,我意識到這一點。我正在處理一些遺留代碼,其中一些以前的靜態方法已被轉換爲非靜態方法。在做一些清理工作時,我注意到這種奇怪的行爲,並想知道PHP中是否存在錯誤。 如果這是不能做的事情,我希望PHP拋出E_ERROR而不是E_STRICT。 –

2

這不是一個真正的錯誤,但更多的結果是沒有真正涵蓋在文檔中。我做了一些研究,並且自己也玩了一些東西,我想我已經明白了,但是我不能100%確定,因爲沒有官方文字可以說明這一點。

我得到的印象是,當你試圖調用一個實例的靜態方法時,它是使用類名稱的等價物,而PHP實際上會這樣調用它,而不是實例。例如$B::getWhy();B::getWhy()相同,核心代碼將如何看到它,無論是否將它傳遞給實例。

您遇到的問題是您將靜態方法稱爲非靜態方法。由於方法的工作方式,他們需要一個範圍來提供諸如self$this之類的東西。現在,通過調用非靜態方法,就好像它是靜態方法一樣,並且考慮到上面關於PHP實際運行代碼的方式,唯一可用的範圍是類A,因爲這是您的範圍,重新來自它。這意味着後期靜態綁定發生,並且由於範圍更改而覆蓋B::$whyA::$why,這正是後期靜態綁定應該達到的目的。

我希望這是有道理的,如果有什麼不清楚的地方,讓我知道,我會盡我所能解釋。

欲瞭解更多信息,有實際剷球這個另外一個問題:Calling non static method with "::"

+0

更改原始代碼並不能解釋原始行爲。我想這已經被要求了。 – Sven

+0

需要在這裏延遲靜態綁定,從靜態::切換到自我::在這裏不是一個選項,除非self ::在非靜態方法中的行爲與靜態方法不同。 –

+0

爲什麼你需要遲到的靜態綁定?你需要添加更多的信息到你原來的帖子,因爲'B'不是'A'的孩子,而是完全獨立的類。 – ollieread

相關問題