抽象类和只有受保护构造函数的类之间有什么区别? (。净)

时间:2010-02-05 19:41:33

标签: c# constructor abstract-class protected

抽象类和只有受保护构造函数的类之间有什么区别?它们似乎与我非常相似,因为你无法实例化任何一个。

编辑:

如何在派生类中创建实例,并使用带有受保护构造函数的基类?例如:

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

    }
}

9 个答案:

答案 0 :(得分:12)

可以在类本身内实例化具有受保护构造函数的类 - 在静态构造函数或静态方法中。这可用于实现单例或工厂类型的东西。

抽象类根本无法实例化 - 意图是一个或多个子类将完成实现,并且这些类将被实例化

编辑:

如果您拨打ProtectedConstructor.GetInstance();而非new ProtectedConstructor();,则可以。也许受保护的构造函数不能以这种方式调用?但是受保护的方法当然可以。

Here是一篇关于该主题的有趣文章。

答案 1 :(得分:3)

大多数情况下,实际上没有什么区别,因为两者都只能通过子类生成。

但是,标记班级abstract有两个好处:

  1. 使用受保护的构造函数,仍然可以通过两种方式创建类的实例。您可以将Activator.CreateInstance与BindingFlags.NonPublic一起使用,也可以使用在类(或子类)中定义的工厂方法来创建类的实例。但是,无法创建标记为抽象的类。

  2. 通过标记班级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)在内的任何方法创建类的实例。