9

What are all the difference between an abstract class, and a class with only protected constructor(s)? They seem to be pretty similar to me, in that you can't instantiate either one.

EDIT:

How would you create an instance in a derived class, with a base class with a protected constructor? For instance:

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

    }
}
4

9 回答 9

12

You can instantiate a class with protected constructors from within the class itself - in a static constructor or static method. This can be used to implement a singleton, or a factory-type thing.

An abstract class cannot be instantiated at all - the intent is that one or more child classes will complete the implementation, and those classes will get instantiated

Edit:

if you call ProtectedConstructor.GetInstance(); instead of new ProtectedConstructor();, it works. Maybe protected constructors can't be called this way? But protected methods certainly can.

Here is an interesting article on the topic.

于 2010-02-05T19:45:32.340 回答
3

Most of the time, there is little practical difference, as both are only able to be generated via a subclass.

However, marking a class abstract has two benefits:

  1. With protected constructors, it's still possible to create an instance of the class in two ways. You can use Activator.CreateInstance with BindingFlags.NonPublic, or you can use a factory method defined in the class (or a subclass) to create an instance of the class. A class marked abstract, however, cannot be created.

  2. You are making your intention more clear by marking the class abstract. Personally, I find this the most compelling reason to do so.

于 2010-02-05T19:46:20.837 回答
1

From an outside , black-box perspective, yes they are similar in that you cannot instantiate either one. However, you can never instantiate an abstract class, where you can construct a class with only protected constructors from within the class itself, or from an inheritor.

于 2010-02-05T19:45:52.943 回答
1

Your example is flawed because in the getInstance case because you construct a ProtectedConstructor class and expect to down cast it as a DerivedClass. Instead you need a slightly more complete implementation where the derived class has a 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"); 
    }
}

Regardless the major difference usage of abstract classes is to define abstract methods that subclasses must implement but you don't want to provide a default implementation for. For example suppose you have some kind of Thread class that has a Run method. You want to ensure that every call to Run first setups up some logging then does the real work of the thread and then stops logging. You could write an abstract Thread class like this:

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");
    }
}
于 2010-02-05T20:33:04.247 回答
1

我没有看到其他人提到的另一件要考虑的事情是,您的代码将来可能会被维护。如果维护者为一个类添加了一个公共构造函数,那么它就可以被实例化。这可能会破坏您的设计,因此您应该阻止它(或设计以适应它)。

为防止其他人进行此类更改,您可以注释您的代码。或者,正如其他人所说,使用“抽象”来明确记录您的意图。

于 2010-02-05T21:17:07.287 回答
1

抽象类可以有抽象方法;仅包含方法签名但不包含子类必须实现的主体的方法。

说真的,还没有人提到过?

于 2010-02-05T20:23:17.537 回答
0

嗯,想到的第一个区别是抽象类不能被实例化,但是具有受保护构造函数的类可以被实例化并抛出另一个公共方法。

一个常见的例子可能类似于单例模式:http ://en.wikipedia.org/wiki/Singleton_pattern

于 2010-02-05T19:48:25.723 回答
0

如果您的意图是只允许静态使用该类(即不将其用作纯基类),那么您应该使用static关键字;CLR 将阻止通过包括反射 (AFAIK) 在内的任何方法创建类的实例。

于 2010-02-05T20:24:47.537 回答
0

如果您从另一个抽象类继承一个抽象类,则不必满足抽象方法,但您可以使用具有受保护 ctor 的普通类。例子


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
}

于 2010-02-05T20:03:22.113 回答