【问题标题】:Does a parent class always need a default or no-argument constructor even if the child class already has a defined constructor?即使子类已经定义了构造函数,父类是否总是需要默认或无参数构造函数?
【发布时间】:2019-12-05 14:49:19
【问题描述】:

我无法编译此代码。

class Horse {
    private int age;
    Horse(int age) {
        this.age = age;
    }
}

class Pony extends Horse {
    private int age;
    Pony(int age) { //here compiler complains about no default constructor in parent class
        this.age = age;
    }
}

我知道当父类只有带参数的构造函数时,你必须为子类定义构造函数,这就是我所做的。但是,编译器抱怨父类没有默认构造函数。

我是否可以得出这样的结论:父类总是需要默认或无参数构造函数?如果我希望父类和子类只有带参数的构造函数怎么办?

【问题讨论】:

    标签: java inheritance parameters constructor default-constructor


    【解决方案1】:

    我是否认为父类总是需要默认或无参数构造函数?

    没有。子类构造函数必须做的第一件事是调用一个超类构造函数。如果你不这样做,那么编译器会为你调用超类的无参数构造函数。但是,如果超类没有,那当然会失败。

    你的代码应该是:

    class Pony extends Horse {
        Pony(int age) {
            super(age);
        }
    }
    

    看,超类已经有一个年龄字段,可能还有使用该字段的方法。所以在子类中重新声明一个是错误的,而且会适得其反。

    【讨论】:

      【解决方案2】:

      要使其编译为您需要调用 super(int) 而不是隐式调用 super()

      Pony(int age) {
          super(age);
          this.age = age;
      }
      

      然后您可能会注意到HorsePony 具有完全相同的字段,其中包含完全相同的数据。如果Pony 类基于(Horse) 已经定义了该字段,为什么Pony 需要字段age

      Pony(int age) {
          super(age);
      }
      

      这是继承的美妙之处:您可以使用任何已经写在基类中的东西。


      但是,编译器抱怨父类没有默认构造函数。

      它抱怨是因为,正如我上面提到的,它未能调用 super()

      如果构造函数体不是以显式构造函数调用开始,并且被声明的构造函数不是原始类 Object 的一部分,则构造函数体隐式以超类构造函数调用“super();”开始,调用不带参数的直接超类的构造函数。

      https://docs.oracle.com/javase/specs/jls/se12/html/jls-8.html#jls-8.8.7


      如果我希望父类和子类只有带参数的构造函数怎么办?

      那么子类应该总是明确地声明它想要调用的父类的构造函数。


      我是否认为父类总是需要默认或无参数构造函数?

      不,只要它的子类不调用super(),就可以有一个没有默认构造函数的父类。

      【讨论】:

        猜你喜欢
        • 2021-05-25
        • 2013-10-25
        • 2020-04-18
        • 1970-01-01
        • 1970-01-01
        • 2021-08-31
        • 2014-04-23
        • 1970-01-01
        • 2014-01-03
        相关资源
        最近更新 更多