[英]C# abstract method with base class only implementation?
請考慮以下問題:
你有一個類'A'作為許多其他類似類的基類,例如。 一個叫B的班級
A類在它自身中很有用(並且已經在整個地方使用過),因此不是抽象的。
關鍵在於您現在希望強制執行一個新協議,要求所有繼承自A(包括A本身)的類實現方法'func()'。 如果子類忘記實現func(),則應該存在編譯器錯誤。
class A {
A func() { ret new A(...) }
}
class B : A {
A func() { ret new B(...) }
}
class C : A {
// Should give error : no func()
}
問題清楚了嗎? 我不能創建A :: func()抽象,因為我希望能夠繼續使用A作為具體類。 我無法使其成為虛擬,因為這會導致子類回退到超類(而不是給編譯器錯誤)。
接近解決方案的唯一方法是創建一個新的抽象類A *並使所有自定義類型繼承自該類,並將A的所有當前用法替換為具有繼承自A *的新類“DefaultA”的具體類。 這看起來很亂。 請告訴我還有其他方法可以做到這一點嗎?
如果子類型不覆蓋特定方法,則根本無法保持A
具體類型並強制編譯器錯誤。
好吧,正如你所說,你可以創建一個繼承自A的中間抽象類X,並要求派生類繼承自X.X然后使用簽名匹配func
聲明一個受保護的抽象方法,並覆蓋來自A的func
以調用該方法。 這是一個例子:
class A {
public virtual A func() { ... }
}
abstract class X : A {
protected abstract A funcImpl();
public override A func() { return funcImpl(); }
}
class B : X { /* must now implement funcImpl() to avoid compiler error */ }
class C : X { /* must now implement funcImpl() to avoid compiler error */ }
這種方法的主要問題是要求所有派生類現在繼承自X而不是A.因此,您只是將執行問題從一種更改為另一種。
在我看來,更ABase
方法是將A
重構為基類ABase
並在那里使用func
。 然后密封A
並要求B
和C
繼承ABase
而不是A
:
class ABase {
public abstract ABase func(); }
sealed class A : ABase {
public override ABase func() { ... }
}
class B : ABase {
// forced to override func()
public override ABase func() { ... }
}
你必須用ABase
替換A
所有用途 - 但是在Visual Studio中有一些優秀的重構工具(以及像ReSharper這樣的第三方工具),這使得它比以前更加痛苦。
如果這是你需要做的,那么是的。
但在我看來,您可能希望重新考慮這一要求。 我經常實現類似的框架,在子類中強制實現是一個聰明的伎倆。 然后我發現,作為這些框架的使用者 ,我會復制代碼或默認為一些無法實現(如空方法)。 這兩者都不是理想的,因為它們會增加雜亂和噪音,並降低可維護性。
此外,如果此模式的應用程序是自行工作(即您的示例具有返回其自身實例的子類),那么您可能希望嘗試不同的東西,例如正確的工廠模式。 呃,通過“嘗試”,我的意思是利用一個控制容器的反轉,如Castle Windsor,Ninject,Unity。
如果A類是抽象的,則無法實例化它。 從而,
new A();
和
abstract A func(); // within the A class definition
是矛盾的。
如果你避開抽象,而轉向虛擬,你可以得到運行時 (不是編譯時)檢查:
// In the A class definition.
protected virtual A func()
{
if (GetType() != typeof(A))
throw // ...
}
基本上,你要我們“讓這個休息,但不要讓這個休息。” 也許你看到了固有的沖突。
這是基類只應用作基類,而不是自己使用的原因之一。
這可能更麻煩,但您可能會強制B,C,D等實現需要func()的接口。 然后確保它們總是通過工廠方法構建。 所以有些模糊:
public class B: A, IFunc{
private B(){}
public static B Create(){ return new B(); }
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.