[英]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
有兩個好處:
使用受保護的構造函數,仍然可以通過兩種方式創建類的實例。 您可以將Activator.CreateInstance與BindingFlags.NonPublic一起使用,也可以使用在類(或子類)中定義的工廠方法來創建類的實例。 但是,無法創建標記為abstract的類。
通過標記類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.