繁体   English   中英

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

[英]What's the difference between an abstract class, and a class with only protected constructors? (.NET)

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

编辑:

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

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

    }
}

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

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

编辑:

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

是一篇关于这个主题的有趣文章。

大多数情况下,几乎没有实际差异,因为两者都只能通过子类生成。

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

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

  2. 通过标记类abstract您可以更清楚地表达您的意图。 就个人而言,我发现这是最有说服力的理由。

从外部,黑盒子的角度来看,是的,它们是相似的,因为你无法实例化任何一个。 但是,您永远不能实例化一个抽象类,您可以在其中构造一个只包含类本身内的受保护构造函数的类,或者从一个继承者构造一个类。

抽象类可以有抽象方法; 只包含方法签名但没有主体的方法,这些子类必须实现。

说真的,没有一个人提到过那个?

您的示例存在缺陷,因为在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");
    }
}

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

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

好吧,首先想到的是,抽象类无法实例化,但是可以实例化具有受保护构造函数的类,抛出另一个公共方法。

一个常见的例子可能是Singleton模式: http//en.wikipedia.org/wiki/Singleton_pattern

如果从另一个抽象类继承一个抽象类,则不必满足抽象方法,而是使用带有受保护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
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM