English 中文(简体)
What s the difference between an abstract class, and a class with only protected constructors? (.NET)
原标题:

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

    }
}
最佳回答

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.

问题回答

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.

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.

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?

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");
    }
}

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.

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

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
}

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).





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签