2012-12-13 54 views
1

我想在我的PHP類中使用函數多態性。我打算爲我的一些子類功能檢查一個函數的輸入類型。PHP函數多態性

class A 
{ 
    public function setValue(Type $value) 
    { 
    } 
} 

class B extends A 
{ 
    public function setValue(XType $value) 
    { 
    } 
} 

class C extends A 
{ 
    public function setValue(ZType $value) 
    { 
    } 
} 
$b = new B(); 
$b->setValue(new XType()); 

class Type {}; 
class XType extends Type; 
class ZType extends Type; 

我找的行爲是PHP拋出一個異常,如果的setValue被稱爲與錯誤的參數類型。

如果我使用上面的代碼,我得到一個錯誤:

Runtime Notice: Declaration of B::setValue() should be compatible with A::setValue(Type $value) in B.php line ..

這是我設法獲得我想要的行爲:

class B extends A 
{ 
    public function setValue(Type $value) 
    { 
     if (!$value instanceof XType) { 
      throw new \Exception("value $value not allowed, should be of type XType"); 
     parent::setValue($value); 
     } 
    } 
} 

但我會很高興讓PHP核心句柄那位代碼對我來說:)

我看到我是不是夠清楚了..

我試圖給調用者提供默認行爲,A :: setValue(),以及關於某些子類的具體行爲,所以如果調用者試圖調用B :: setValue方法()與不支持的類型,它會得到一個錯誤,但如果它調用,讓我們說,d :: setValue方法(),它會得到默認,A :: setValue方法()

+5

你有什麼問題嗎? – eisberg

+0

哈哈,是的!我想知道是否有辦法實現我在不使用instanceof部件的情況下獲得的相同行爲:) –

+0

方法參數類型是逆變的。 – phant0m

回答

1

你已經工作了,沒有必要檢查你正在做的instanceof。你可以在參數類型提示中聲明類型。

你的代碼有什麼問題是它不適合多態。這也是通知(注意:不是錯誤)想告訴你。您的子類需要與父類不同的參數類型。即使這些類型是相關的,這意味着您不能用任何給定的父類的實例替換子類之一。這就是打破多態。如果你的孩子類需要更專門的類型,他們的聲明不再與他們的父母兼容,因此它們不是完全多態的。

在適當的多態性,這應該工作:

if (rand(0, 1)) { 
    $obj = new A; 
} else { 
    $obj = new B; 
} 

$obj->setValue(new Type); 

隨着你想這樣做是行不通的。

+0

好的,我明白你的意思了......我應該更具體地瞭解我的需要,我會編輯我的問題,謝謝! –

+0

我明白你想要做什麼,但答案並沒有真正的區別。 :)你應該*不*縮小或改變一個函數在其子項中接受的類型。我明白這是一個簡單的誘惑,但問問自己爲什麼你這樣做。你明確地讓某些類依賴於某些其他類。這是兩個繼承鏈結合在一起。如果他們密切相關,他們爲什麼不在同一個班級或以其他方式明確配對?也許這是一個合理的用例,但如果真的需要的話,先考慮一下。 – deceze

+0

我沒有在類中聲明類型,因爲Type在不同的類中使用。爲了讓您瞭解我想實現的目標,請查看http://www.graphviz.org/content/attrs I我試圖將所有屬性和屬性類型映射到OO樣式類。 屬性表示我的類A,B,C和屬性類型XType,YType等我想確保A使用正確的類型 –