views:

250

answers:

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

    }
}
+11  A: 

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.

Ray
You can also instantiate the class from a subclass, or via reflection.
Reed Copsey
yes - thanx for the additional info
Ray
True, but in that case it would make more sense to mark them private.
Jonathan Allen
But in that case base() won't work in a derived class. Marking them private or protected results in different behavior.
Brian
+1  A: 

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.

Robin
How would you do it from an inheritor? I've edited the question above.
David Hodgson
A protected constructor can only be called by an inherited class's constructor (i.e. public DerivedClass() : base() will work), not from methods in the inherited class. I am not sure of the reasoning.
technophile
+2  A: 

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.

Reed Copsey
A: 

Well, the first difference that comes to mind is that an abstract class can not be instantiated, but a class with protected constructors could be instantiated throw another public method.

A common example of this might be something like the Singleton pattern: http://en.wikipedia.org/wiki/Singleton_pattern

Andrew Dunaway
A: 

if you inherit an abstract class from another abstract class, you do not have to satisfy abstract methods, but you do with a normal class with protected ctors. Examples


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
}

JMarsch
+1  A: 

An abstract class can have abstract methods; methods that consist only of the method signature, but no body, that child classes must implement.

Seriously, not one person mentioned that yet?

R. Bemrose
A: 

If your intent is to only allow static uses of the class (i.e. not to use it as a pure base class) then you should use the static keyword instead; the CLR will prevent instances of the class being created via any method including Reflection (AFAIK).

technophile
+1  A: 

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");
    }
}
Jon Palmer
@Jon Sorry, I didn't mean to have that downcast; I've edited the question. I was trying to say that you can't instantiate ProtectedConstructor, even in a derived class.
David Hodgson
+1  A: 

Another thing to consider, that I didn't see other people mention, is that your code may be maintained in the future. If the maintainer adds a public constructor to a class, then it can be instantiated. This might break your design, so you should prevent it (or design to accommodate it).

To prevent other people from making these kinds of changes, you can comment your code. Or, as other people said, use "abstract" to explicitly document your intent.

Merlyn Morgan-Graham