簡體   English   中英

抽象類和只有受保護構造函數的類之間有什么區別? (。凈)

[英]What's the difference between an abstract class, and a class with only protected constructors? (.NET)

抽象類和只有受保護構造函數的類之間有什么區別? 它們似乎與我非常相似,因為你無法實例化任何一個。

編輯:

如何在派生類中創建實例,並使用帶有受保護構造函數的基類? 例如:

public class ProtectedConstructor
{
    protected ProtectedConstructor()
    {

    }

    public static ProtectedConstructor GetInstance()
    {
        return new ProtectedConstructor(); // this is fine
    }
}

public class DerivedClass : ProtectedConstructor
{

    public void createInstance()
    {
        ProtectedConstructor p = new ProtectedConstructor(); // doesn't compile
    }

    public static ProtectedConstructor getInstance()
    {
        return new ProtectedConstructor(); // doesn't compile

    }
}

可以在類本身內實例化具有受保護構造函數的類 - 在靜態構造函數或靜態方法中。 這可以用於實現單件或工廠類型的東西。

抽象類根本無法實例化 - 意圖是一個或多個子類將完成實現,並且這些類將被實例化

編輯:

如果你調用ProtectedConstructor.GetInstance(); 而不是new ProtectedConstructor(); , 有用。 也許受保護的構造函數不能以這種方式調用? 但受保護的方法當然可以。

是一篇關於這個主題的有趣文章。

大多數情況下,幾乎沒有實際差異,因為兩者都只能通過子類生成。

但是,標記類abstract有兩個好處:

  1. 使用受保護的構造函數,仍然可以通過兩種方式創建類的實例。 您可以將Activator.CreateInstance與BindingFlags.NonPublic一起使用,也可以使用在類(或子類)中定義的工廠方法來創建類的實例。 但是,無法創建標記為abstract的類。

  2. 通過標記類abstract您可以更清楚地表達您的意圖。 就個人而言,我發現這是最有說服力的理由。

從外部,黑盒子的角度來看,是的,它們是相似的,因為你無法實例化任何一個。 但是,您永遠不能實例化一個抽象類,您可以在其中構造一個只包含類本身內的受保護構造函數的類,或者從一個繼承者構造一個類。

抽象類可以有抽象方法; 只包含方法簽名但沒有主體的方法,這些子類必須實現。

說真的,沒有一個人提到過那個?

您的示例存在缺陷,因為在getInstance情況下,您構造一個ProtectedConstructor類並期望將其轉換為DerivedClass。 相反,你需要一個稍微更完整的實現,其中派生類有一個constrcutor:

public class ProtectedConstructor
{
    protected ProtectedConstructor(string arg)
    {
        // do something with arg
    }

    public static ProtectedConstructor GetInstance()
    {
        return new ProtectedConstructor("test"); 
    }
} 

public class DerivedClass : ProtectedConstructor
{
    protected DerivedClass(string arg) : base(arg)
    {
    }

    public void createInstance()
    {
        DerivedClass p = new DerivedClass("test"); 
    }

    public static DerivedClass getInstance()
    {
        return new DerivedClass("test"); 
    }
}

無論抽象類的主要區別用法是定義子類必須實現的抽象方法,但您不希望為其提供默認實現。 例如,假設您有某種具有Run方法的Thread類。 您希望確保每次調用Run都先設置一些日志記錄,然后執行該線程的實際工作,然后停止記錄。 你可以編寫一個這樣的抽象Thread類:

public abstract Thread
{
    protected Thread()
    {
    }

    public void Run()
    {
        LogStart();
        DoRun();
        LogEnd();
    }

    protected abstract DoRun();

    private void LogStart()
    {
         Console.Write("Starting Thread Run");
    }

    private void LogEnd()
    {
         Console.Write("Ending Thread Run");
    }
}


public class HelloWorldThread : Thread
{
    public HelloWorldThread()
    {
    }

    protected override DoRun()
    {
        Console.Write("Hello World");
    }
}

我沒有看到其他人提到的另一件事是,您的代碼可能會在將來維護。 如果維護者將一個公共構造函數添加到一個類,那么它可以被實例化。 這可能會破壞您的設計,因此您應該阻止它(或設計以適應它)。

為了防止其他人進行這些更改,您可以對代碼進行注釋。 或者,正如其他人所說,使用“抽象”來明確記錄您的意圖。

好吧,首先想到的是,抽象類無法實例化,但是可以實例化具有受保護構造函數的類,拋出另一個公共方法。

一個常見的例子可能是Singleton模式: http//en.wikipedia.org/wiki/Singleton_pattern

如果從另一個抽象類繼承一個抽象類,則不必滿足抽象方法,而是使用帶有受保護ctors的普通類。 例子


public abstract class Parent
{
  protected abstract void AMethod();
}

public abstract class Child: Parent
{
  // does not implement AMethod, and that's ok
}

public class Child2: Parent
{
  // does not implement AMethod, and that will cause a compile error
}

如果你的意圖是只允許靜態使用類(即不要將它用作純基類),那么你應該使用static關鍵字; CLR將阻止通過包括Reflection(AFAIK)在內的任何方法創建類的實例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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