创建类的受保护构造函数有啥好处和坏处

Posted

技术标签:

【中文标题】创建类的受保护构造函数有啥好处和坏处【英文标题】:What are the benefits and the disadvantages of creating a protected constructor of a Class创建类的受保护构造函数有什么好处和坏处 【发布时间】:2012-01-27 00:07:23 【问题描述】:

我有一个愚蠢的疑问,但我想听听一些关于它的意见。

我有一个超类(MySuperClass),然后,我有大约 70 个类继承自这个超类(Bean 类)。

这个超类的目的是使用反射来实现“toString”方法,通过这种方式,我可以确保所有这 70 个类都有 toString 方法。这70个类都是bean,最终目的是记录类信息而不仅仅是类的实例。

但是,这不是我想讨论的,我想听听您对超类的受保护构造函数的看法,拥有它的好处和坏处,而不仅仅是针对这种特殊情况但对于您可以想象的其他情况或场景。

问候,

【问题讨论】:

【参考方案1】:

如果您的目标是确保MySuperClass 永远不会直接通过new MySuperClass() 实例化,只有它的子类是,那么声明类abstract 更有意义;见http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html。这就是抽象类的全部意义所在。那么构造函数可以是public 或者protected,这并不重要。

-abstract 类中包含所有构造函数 protected 的原因是如果您确实打算使用 new MySuperClass() 实例化该类本身,但只希望它被 子类和其包的其他成员(例如“工厂”对象)实例化。不过,这听起来不像您想要做的。

【讨论】:

好吧,将构造函数声明为受保护的目的是禁止我的超类的公共实例化。但我想听听对此的一些意见。 @FernandoMoyano:是的,但是为什么你要禁止你的超类的公共实例化?听起来您真正想要 - 或真正应该想要 - 根本不允许您的超类的任何直接实例化。也就是说,除了作为一个超类之外,这个类听起来毫无用处,而且没有理由让这个超类的实例不是其子类之一的实例。 谢谢@ruakh,我想你已经准确地描述了我想要做的事情:“......根本不允许你的超类的任何直接实例化。也就是说,听起来这个类是无用的除了作为超类,没有理由让这个超类的实例不是其子类之一的实例......" @FernandoMoyano:那么,这意味着你想要一个抽象类。请参阅我的答案中的链接。 :-)【参考方案2】:

如果您只想使用返回此类型实例的静态方法创建一个实例,则可以使构造函数受保护。当对象很重并且创建许多实例会影响内存时,有利于内存分配

public class A
   private static A instance = null;
   protected A() 
      // Exists only to defeat instantiation.
   
   public static A getInstance() 
      if(instance == null) 
         instance = new A();
      
      return instance;
   

【讨论】:

同一个包中的B类可以说A a = new A();。再见,你的单身。 嗨@HusseinX,感谢您的回答。我不是在寻找单身人士,@ruakh 已经正确地描述了我想要做的事情。【参考方案3】:

受保护的构造函数有一个抽象类不具备的有用特性:同一个包中的类、子类和类本身的静态方法可以创建该类的实例,而外部人员则不能。抽象类根本无法实例化,无论构造函数的可访问性如何。

话虽如此,我更希望类是抽象的。受保护的构造函数不能阻止子类或同一包中的任何类说出BaseClass x = new BaseClass();。一个受保护的构造函数对我说“代码可能在某个地方实例化了这个类”,并给了我另一件事需要跟踪。

【讨论】:

嗨@cHao,感谢我们的回答。这不能是一个抽象类,因为它使用反射实现了 to string 方法。 抽象类中的反射有一些限制吗?对我来说新闻...抽象类应该具有与非抽象类相同的功能,当然不包括实例化的能力。 哎呀,你说得对,我刚刚测试过,效果很好。我确信这是不可能的。谢谢@cHao

以上是关于创建类的受保护构造函数有啥好处和坏处的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中调用类的受保护构造函数

请问把基类构造函数声明为protected有啥好处呢(抽象基类)

具体类中的受保护构造函数与抽象类中的公共构造函数

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

C++:为啥我的 DerivedClass 的构造函数无法访问 BaseClass 的受保护字段?

我无法访问我的基类的受保护成员