2011-04-01 81 views
12

與問題快速代碼包括:抽象父類中的PHP靜態變量:問題在示例代碼中!

abstract class ClassParent { 
    public static $var1 = "ClassParent"; 
} 

class ClassChild1 extends ClassParent{ 
    public static function setvar1(){ 
     ClassChild1::$var1 = "ClassChild1";  
    } 
} 

class ClassChild2 extends ClassParent{ 
    public static function setvar1(){ 
     ClassChild2::$var1 = "ClassChild2"; 
    } 
} 


ClassChild1::setvar1(); 

echo ClassChild2::$var1; 
// Returns "ClassChild1". Shouldn't this still be "ClassParent"? 

我假設上述預期的行爲,而不是一個PHP錯誤。在那種情況下,我怎麼能在父類中聲明一個靜態變量,這個靜態變量將被分別處理給子類。換句話說,我希望每個孩子都有獨立的靜態值。我是否必須特別在子類中聲明靜態變量,或者可能有另一種方法?

謝謝!

回答

16

編輯:在進一步調查中,我認爲你所要求的不是直接可能的,即使是遲到的靜態綁定。其實,我有點驚訝。

The answer to this question提供了一些解決方法。

原來的答覆:


在父類,如果你指的是形式的靜態變量:

self::$var 

它會使用相同的變量在所有的繼承類(因此所有子類將仍然訪問父類中的變量)。

這是因爲關鍵字self的綁定是在編譯時完成的,而不是在運行時完成的。

從PHP 5.3開始,PHP支持使用static關鍵字的後期靜態綁定。所以,在你的類,參考變量與:

static::$var 

和「靜態」將被解析爲在運行時的子類,所以會有每個子類單獨的靜態變量。

+0

感謝您的回答。我正在使用5.3。這不應該與我上面編碼的有什麼不同 - 我只是明確指出類名而不是使用「靜態」。事實上,將它們改爲靜態也會產生相同的結果。 – Aron 2011-04-01 13:04:03

+0

...似乎工作的唯一的東西是如果我顯式聲明子類中的變量。但是 - 如果可能的話 - 我想避免這個解決方案... – Aron 2011-04-01 13:05:03

+0

當我發佈我的答案時,你的代碼片段並不完整。我不認爲這是一個乾淨的解決方案。我用更多的信息更新了我的答案。 – Lauren 2011-04-01 13:07:08

3

感謝您的回答!我遇到了一些我無法跟蹤的問題,這幫助我解決了這些問題。 :)

您可能有興趣知道此行爲有一個bug report其中包括解決方法。在你的情況,這將是:

class ClassChild1 extends ClassParent{ 
    public static function setvar1(){ 
     $tmp = 'x'; 
     static::$var1 =& $tmp; // break reference 
     // and now this works as expected: (changes only ClassChild1::$var1) 
     static::$var1 = "ClassChild1";  
    } 
} 
// do the same in ClassChild2... 

醜得要命,我同意 - 但PHP按預期工作這種方式,再加上它沒有副作用。

這確實是一個非常令人懷疑(並且記錄不完整)的「特徵」在我眼中 - 讓我們希望他們有一天會改變它。

+1

請注意,這被宣佈爲'不是一個錯誤'。即使它是一個功能,它應該被記錄:)。 – 2013-02-19 13:32:54

+0

好吧,'magic_quotes'和'safe_mode'也不是bug,但是男孩當我們移除它們時很高興。 ;)PHP開發人員有一些歷史(當然,在我的眼中)是糟糕的設計決策,這當然是其中之一(又是:IMnsHO)。 – johndodo 2013-02-22 13:34:27

+0

我期待(沒有測試)在兩個子類中重新聲明$ var1作爲靜態函數也應該完成這項工作。而且這將是一個不那麼醜陋的地獄;) – 2016-02-24 15:57:02