2008-11-28 170 views
2

我正在處理一個大型的代碼庫,它在這些類中有很多類和很多抽象方法。我對以下情況下我應該做的事情感興趣。抽象方法的默認實現

如果我有一個帶有抽象方法的Parent-A類。只有兩個孩子。如果Child-B實現AbstractMethodA但Child-B不適用。

我應該

  1. 從母體中取出抽象的關鍵字,並使用虛擬的或動態?
  2. 提供該方法的空實現。
  3. 提供一個實現,如果調用會引發錯誤。
  4. 忽略警告。

編輯:謝謝你的所有答案。它證實了我的懷疑,認爲這不應該發生。經過進一步調查後發現這些方法根本沒有使用,所以我已經完全刪除了它們。

回答

9

如果AbstractMethodA不適用於Child-B,則Child-B不應該從Parent-A繼承。

或者,如果Child-B從Parent-A繼承,並且AbstractMethodA不適用於子級,則它不應該在父級中。

通過在Parent-A中添加一個方法,您表示該方法適用於Parent-A及其所有子項。這就是繼承意味着,如果你用它來表示不同的東西,你最終會與編譯器發生嚴重的爭執。

[編輯 - 也就是說,如果該方法確實適用,Mladen Prajdic的答案沒問題,但對於涉及的一個或多個類別應該什麼也不做。一種什麼都不做的方法是與不適用的方法不同,但也許我們並不是指「不適用」的同一個事物]

另一種技術是在Child中實現該方法-B無論如何,但要讓它像總是返回失敗一樣激烈,或者拋出異常或其他東西。它的工作原理,但應該被認爲是一個閃光點,而不是一個乾淨的設計,因爲這意味着來電者需要知道他們有什麼東西,他們對待父母A是真的一個孩子B和因此他們不應該調用AbstractMethodA。基本上你已經拋棄了多態,這是OO繼承的主要好處。就我個人而言,我更喜歡這樣做,因爲在基類中有一個拋出異常的實現,因爲這樣子類就不會「意外」地通過「遺忘」來執行該方法。它必須實現它,如果它實現它不起作用,那麼它明確地這樣做。糟糕的情況應該是嘈雜的。

0

使其在基類中虛擬爲空,並在子類中覆蓋它。

0

您可以使用接口。然後Child-A和Child-B都可以實現不同的方法,並仍然繼承Parent-A。接口像抽象方法一樣工作,因爲它們迫使類實現它們。

2

如果後代實現不是強制性的,那麼你應該去1 + 2(在祖先即空的虛擬方法)

0

如果一些亞類(B1,B2,......)的A用於其方法的不同子集(C1,C2,...),可以說A可以在B和C中分開。

我不知道德爾福太好了(根本不是:)),但我認爲就像例如在Java和COM中,一個類可以'實現'多個接口。在C++中,這隻能通過多次繼承抽象類來實現。

更具體一點:我會創建兩個抽象類(使用抽象方法),並更改繼承樹。

如果這不可行,解決方法可以是「適配器」:一箇中間類A_nonB_,所有B方法都實現爲空(並且在調用它們時產生警告)以及A_nonC_。然後更改繼承樹來解決您的問題:B1,B2,...從A_nonC_繼承,C1,C2 ...從A_NonB_繼承。

1

我認爲,一般來說,如果您無法首先實現所有抽象方法,則不應該從抽象類繼承,但我知道在某些情況下它仍然有意義(請參閱Stream類及其實現)。

我認爲你應該創建這些抽象方法的實現,拋出一個NotImplementedException。

您也可以嘗試使用ObsoleteAttribute,以便調用該特定的方法將是編譯時錯誤(當然,拋出NotImplementedException)。請注意,ObsoleteAttribute並不完全用於此目的,但我想如果您在評論中使用了有意義的錯誤消息,那沒有關係。

強制性代碼例如:

[Obsolete("This class does not implement this method", true)] 
public override string MyReallyImportantMethod() 
{ 
    throw new NotImplementedException("This class does not implement this method."); 
}