为啥抽象类的构造函数应该受到保护,而不是公开的?

Posted

技术标签:

【中文标题】为啥抽象类的构造函数应该受到保护,而不是公开的?【英文标题】:Why should constructors on abstract classes be protected, not public?为什么抽象类的构造函数应该受到保护,而不是公开的? 【发布时间】:2010-10-20 04:44:23 【问题描述】:

ReSharper 建议将 abstract 类中 public 构造函数的可访问性更改为 protected,但并未说明其背后的基本原理。

你能解释一下吗?

【问题讨论】:

【参考方案1】:

仅仅是因为在抽象类中公开是没有意义的。根据定义,抽象类不能直接实例化。它只能由派生类型的实例实例化。因此,唯一应该可以访问构造函数的类型是它的派生类型,因此受保护比公共更有意义。它更准确地描述了可访问性。

【讨论】:

换句话说:你为什么要用无用的垃圾污染别人的智能感知? @Andre 构造函数仅在智能感知中显示新调用和基本调用。通常抽象类在考虑可访问性之前会从新类中过滤掉,因为检查抽象非常容易且便宜。 既然如此,编译器不应该强制抽象类不能public构造函数吗? 我来到这里是因为我正在寻找答案,如果抽象类不存在我该怎么办。我在想如果给构造函数一个受保护的访问将是一个解决方案。那么,在抽象类被发明之前,也许就像过去那样?这就是为什么程序员应该在抽象类中使用受保护的构造函数,因为这是一种传统?我不是老程序员,我只是想知道它是怎么回事。最新的 Visual Studio 没有显示任何警告,所以我认为这只是个人喜好问题。 我没有看到这个问题这么老。在那些日子里,这个问题在 MSDN (msdn.microsoft.com/en-us/library/ms182126.aspx) 中有描述。 Andrew Troelsen 和 Philip Japikse 在他们的“C# 6.0 和 .NET 4.6 框架”一书中(我认为这本书非常好)在他们的示例中使用公共构造函数来展示抽象类,而没有提及受保护的类。【参考方案2】:

如果您在抽象类上创建构造函数public 而不是protected,从技术上讲,这没有任何区别。构造函数的可访问性/可见性仍然完全相同:相同的类或派生类。这两个关键字在所有意图和目的上都具有无法区分的效果。

所以,这个选择只是风格问题:输入protected 以满足精明的面向对象的人。


默认情况下,反射只会包含 public 的构造函数,但无论如何你都不能调用该构造函数。

IntelliSense 将在键入 new 时显示 public 构造函数,但无论如何您都无法调用该构造函数。

程序集的元数据将反映构造函数是公共的还是受保护的这一事实。

【讨论】:

除非将可见性声明为public 是不真实的。 他的回答给出了两者之间的功能差异,这正是我所寻找的。是否真实并不重要,除此之外,这是 c# 语言要解决的问题,而不是开发人员。【参考方案3】:

这是很好的 OO 实践。

public abstract class ExampleAbstractClass

    protected ExampleAbstractClass()
    
      // :::
    

您只希望继承的子类可以访问构造函数。做到这一点的唯一方法是使构造函数受到保护。 请记住,当您向这些构造函数添加参数时,这是一个完全不同的讨论。

【讨论】:

添加参数时有何不同?构造函数仍然只会被派生类调用。 它将强制所有继承构造函数在其签名中包含参数,无论是否需要。 @SrikarDoddi:不,它没有。继承的构造函数只需要调用: base(...) 并传递一些东西,但这些东西也可以是从其他地方检索到的常量或值。

以上是关于为啥抽象类的构造函数应该受到保护,而不是公开的?的主要内容,如果未能解决你的问题,请参考以下文章

为啥Java抽象类中需要受保护的构造函数

为啥不能将继承的受保护构造函数公开?

抽象类的 C++ 保护构造函数

抽象类的受保护与公共构造函数?有区别吗?

为啥自动对象的析构函数被调用两次?

析构函数为啥能释放对象内存?