2012-03-02 38 views
2
abstract class Mother { 
     protected static $foo = null; 
     protected static $bar = null; 

     public function getFoo() { return static::$foo; } 
     public function getBar() { return static::$bar; } 
     public function setFoo($foo) { static::$foo = $foo; } 
     public function setBar($bar) { static::$bar = $bar; } 
} 

class Brother extends Mother { 
     protected static $foo = 'BROTHERS'; 
} 

class Sister extends Mother { 
     protected static $foo = 'SISTERS'; 
} 

$brother1 = new Brother(); 
$brother2 = new Brother(); 
$sister1 = new Sister(); 
$sister2 = new Sister(); 

$sister1->setBar('ONLY SISTERS'); // We set $bar = 'ONLY SISTERS' at sister1. 
// We want only Sister instances to get this value... 
// however Brother instances also get this value! 

    echo '<p>Brother 1: Foo="'.$brother1->getFoo().'", Bar="'.$brother1->getBar().'"</p>'; 
// Foo="BROTHERS", Bar="ONLY SISTERS" 
    echo '<p>Brother 2: Foo="'.$brother2->getFoo().'", Bar="'.$brother2->getBar().'"</p>'; 
// Foo="BROTHERS", Bar="ONLY SISTERS" 
    echo '<p>Sister 1: Foo="'.$sister1->getFoo().'", Bar="'.$sister1->getBar().'"</p>'; 
// Foo="SISTERS", Bar="ONLY SISTERS" 
    echo '<p>Sister 2: Foo="'.$sister2->getFoo().'", Bar="'.$sister2->getBar().'"</p>'; 
// Foo="SISTERS", Bar="ONLY SISTERS" 

很顯然,如果每個孩子(兄弟姐妹)都沒有明確地重新定義靜態:: $ bar,他們的父母(母親)會爲他們設置值(或者至少對於那些沒有重新定義它的人)。PHP:將靜態變量範圍限制到特定的類

問題:有什麼辦法可以防止沒有重新定義static :: $ bar的孩子接收新值嗎?換句話說,如何確保只有被引用的類才能獲得新的值,即使靜態:: $ bar沒有在每個孩子中被明確地重新定義,也是如此?

+1

我看到的只有一個選項來實現這一目標。你必須覆蓋姐妹類中的getBar和setBar方法。 setBar方法寫入$ this-> bar,getBar檢查是否設置了$ this-> bar,否則從parent :: $ bar中檢索。 – Dan 2012-03-02 20:26:49

+0

當有對象實例時,是否有這些靜態的原因? – 2012-03-02 20:28:49

+0

@丹你可能是對的。另一種選擇是在每個孩子中重新聲明static :: $ bar。問題是沒有辦法強迫程序員這樣做。 – mae 2012-03-02 20:42:32

回答

2

不,不是你這樣做的方式。這就是私人範圍的用途。子類繼承所有公共和受保護的靜態屬性 - 這意味着它們都指向相同的值,無論它們是父級,子級還是兄弟。

這是正確的,很好的面向對象。

您應該在父類中將它定義爲私有靜態,然後該子將不能直接看到它,並且可以根據需要使用相同的名稱創建它們自己的私有靜態變量。

在你的類中提供靜態獲取器和設置器來訪問私有靜態屬性。

Brother::getFoo(); 
Sister::getFoo(); 

您可以進行的getFoo()在父類中的母親抽象的或沒有,如果需要直接訪問它使非抽象的,所以你可以這樣做:

Mother::getFoo(); 
+0

好吧我認爲這是正確的方向,但我需要一些更多的細節來說明如何(以及在​​哪裏)實現這些功能,特別是$ bar getter/setter,因爲我不斷收到此錯誤,我嘗試了任何操作:_Fatal error:無法訪問屬性Sister :: $ bar_ – mae 2012-03-02 21:13:58

+0

我應該在**每個**子類中提供靜態獲取者/設置者嗎? – mae 2012-03-02 22:39:20

+0

您可以在Mother類中創建一個,它將通過Mother :: getBar()訪問Mother :: $ bar。是的,您需要爲所有類實現getter和setter,因爲$ bar對於Mother來說是私有的。 – Ray 2012-03-03 03:46:43

1

這只是瘋狂。

您應該明白,extend定義爲IS A的關係。例如:class Duck extends Bird{}這意味着每個Duck實例都是Bird

因此,在您的示例中,每個BrotherMother。我看不出這是如何理解的。


而另一件事:你爲什麼要濫用靜態變量?你在做什麼沒有面向對象的編程。你只是將全局作用域變量和函數包裝在命名空間中(這看起來像是類)。

關於這個問題的一些額外的鏈接,你會覺得非常有用:

+0

所以你認爲最好在每個子類中都有一個相同字符串的副本? – mae 2012-03-05 15:32:04

+0

@ user1132363,什麼?我在哪裏說的?也許你應該學習依賴注入。 – 2012-03-05 15:47:36

+1

那麼你明確暗示我不應該使用靜態變量。至少不是我現在這樣做 - 但你沒有提供任何替代解決方案。 – mae 2012-03-05 15:57:53