抽象类和只有受保护构造函数的类之间有什么区别?它们似乎与我非常相似,因为你无法实例化任何一个。
编辑:
如何在派生类中创建实例,并使用带有受保护构造函数的基类?例如:
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
}
}
答案 0 :(得分:12)
可以在类本身内实例化具有受保护构造函数的类 - 在静态构造函数或静态方法中。这可用于实现单例或工厂类型的东西。
抽象类根本无法实例化 - 意图是一个或多个子类将完成实现,并且这些类将被实例化
编辑:
如果您拨打ProtectedConstructor.GetInstance();
而非new ProtectedConstructor();
,则可以。也许受保护的构造函数不能以这种方式调用?但是受保护的方法当然可以。
Here是一篇关于该主题的有趣文章。
答案 1 :(得分:3)
大多数情况下,实际上没有什么区别,因为两者都只能通过子类生成。
但是,标记班级abstract
有两个好处:
使用受保护的构造函数,仍然可以通过两种方式创建类的实例。您可以将Activator.CreateInstance与BindingFlags.NonPublic一起使用,也可以使用在类(或子类)中定义的工厂方法来创建类的实例。但是,无法创建标记为抽象的类。
通过标记班级abstract
,您可以更清楚地表达自己的意图。就个人而言,我认为这是最有说服力的理由。
答案 2 :(得分:1)
从外部,黑盒子的角度来看,是的,它们是相似的,因为你无法实例化任何一个。但是,您可以从不实例化一个抽象类,在该类中,您可以从类本身或从继承者构造仅包含受保护构造函数的类。
答案 3 :(得分:1)
抽象类可以有抽象方法;仅由方法签名组成的方法,但没有主体,子类必须实现。
说真的,没有一个人提到过吗?
答案 4 :(得分:1)
您的示例存在缺陷,因为在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");
}
}
答案 5 :(得分:1)
另一件需要考虑的事情是,我没有看到其他人提到的是,您的代码可能会在将来维护。如果维护者将一个公共构造函数添加到一个类,那么它可以被实例化。这可能会破坏您的设计,因此您应该阻止它(或设计以适应它)。
为防止其他人进行此类更改,您可以对代码进行评论。或者,正如其他人所说,使用“抽象”来明确记录您的意图。
答案 6 :(得分:0)
嗯,首先想到的是,抽象类无法实例化,但是可以实例化具有受保护构造函数的类,抛出另一个公共方法。
一个常见的例子可能是Singleton模式:http://en.wikipedia.org/wiki/Singleton_pattern
答案 7 :(得分:0)
如果从另一个抽象类继承抽象类,则不必满足抽象方法,而是使用带有受保护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
}
答案 8 :(得分:0)
如果您的目的是仅允许静态使用该类(即不将其用作纯基类),那么您应该使用 static 关键字; CLR将阻止通过包括Reflection(AFAIK)在内的任何方法创建类的实例。