【问题标题】:Are Constructors not members of a class?构造函数不是类的成员吗?
【发布时间】:2014-08-04 21:13:46
【问题描述】:

构造函数不是类的成员吗?如果是,为什么不能继承?

JLS 7.0 says that constructors are not members,因此不能被继承。仅对 Java 来说是这样,还是一般的 OOP 范式?

【问题讨论】:

  • 这是在哪里说的?
  • JLS 7.0 PDF 版本中的第 8.2 节,第 197 页。
  • 在c++中要继承你必须将其设置为虚拟,关于java-idk
  • super() 用于调用 Java 的父构造函数。
  • 如果你仔细想想,构造函数是类的一部分,而不是实例。

标签: java oop inheritance constructor


【解决方案1】:

构造函数不是出于良好的设计原因而被继承的。如果它们是继承的,那么在尝试将它们隐藏在继承的类中时会遇到问题。

考虑这个例子:

class Plane{
    public Plane(int passengerCapacity, int cargoCapacity){...}
}
class F18 extends Plane{
    public F18(){
        super(0,0);
        ....
    }
}

现在,下面的构造函数有意义吗?

Plane p = new F18(0,0);

并非如此,因为子类是父类的特例。在这个特定的示例中,在 F18 类中提供 Plane 构造函数是没有意义的;子类希望控制父类的构造方式。

如果构造函数被继承并且有人希望隐藏父构造函数,他们可能会尝试执行以下操作:

class F18{
    Plane innerPlane;
    public F18(){
        innerPlane = new Plane(0,0);
    }
}

不是真正的解决方案,因为在每个方法和属性中,都必须写 return innerPlane.SomeMethod();,这几乎违背了继承的目的。

此原则也适用于其他 OOP 语言(例如 C#)。

但如果我真的想在很多子类中继承构造函数怎么办...

那么你的架构是错误的。您实际上并不需要继承来解决您的问题。您可以抽象另一个基类/接口中不同的部分。例如

class Plane{
    IPilot Pilot;
    public Plane(int passengerCapacity, int cargoCapacity, IPilot pilot){...}
}

构造函数是构造对象的方法。您真的需要许多可以以相同方式构造的子类(并且使用相同的逻辑,因为它们是继承的),还是需要一个可以灵活交换其某些组件的类?

【讨论】:

  • 可能还想补充一点,super() 也可以调用 defaultprivate 构造函数,以“良好的设计原因”。
  • 谢谢,凯森!这个解释很贴切。
【解决方案2】:

在大多数范例中,继承构造函数的概念没有意义;而是以相反的继承顺序调用构造函数,例如,如果您有:

Pidgeon -> Bird -> Animal

其中-> 表示“继承自”,然后要构造Pidgeon,它首先调用Animal 构造函数,然后是Bird 构造函数,最后是Pidgeon 构造函数。如果它没有这样做,那么您将不得不初始化您继承的类的所有成员或手动调用基类的构造函数(因为您可能必须这样做 无论如何如果你有特定的参数要传递)。

或者,换一种说法,虽然派生类中的函数通常替换基类中的函数,但构造函数扩展基类中的函数。

【讨论】:

    【解决方案3】:

    尽管您可能听说过,但这不是一般的 OOP 范例。我认为,有一些旧的 OOP 语言,其中构造函数只是普通方法。但是目前许多流行的语言以不同的方式对待构造函数,就像其他方法一样。这是一个不完美的解决方案,会导致一些变通方法,例如 Beans 规范中建议只有无参数构造函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-11
      • 1970-01-01
      相关资源
      最近更新 更多