簡體   English   中英

C#抽象方法只用基類實現?

[英]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並要求BC繼承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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM