Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a parent class always need a default or no-argument constructor even if the child class already has a defined constructor?

I cannot get this code to compile.

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;
    }
}

I know you must define a constructor for a child class when the parent class only has constructors with parameters, and that is what I have done. However, the compiler complains that the parent class has no default constructor.

Am I right to conclude that a parent class always needs a default or no-arg constructor? What if I want the parent and child class to only have constructors with parameters?

like image 980
K Man Avatar asked Jul 27 '19 16:07

K Man


2 Answers

Am I right to conclude that a parent class always needs a default or no-arg constructor?

No. The first thing a subclass constructor must do is to invoke one of the superclass constructors. If you don't, then the compiler calls the no-arg constructor of the superclass for you. But of course that fails if the superclass doesn't have one.

Your code should be:

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

See, the superclass already has an age field, and probably methods that use that field. So redeclaring one in the subclass is wrong and counter-productive.

like image 173
JB Nizet Avatar answered Sep 20 '22 16:09

JB Nizet


To make it compile to you need to call super(int) instead of calling super() implicitly.

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

Then you may notice that both Horse and Pony have exactly the same field which holds exactly the same data. Why would Pony need to have the field age if the class Pony is based on (Horse) already defined this field?

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

It's the beauty of inheritance: you may make use of anything that was already written in the base class.


However, the compiler complains that the parent class has no default constructor.

It complains because, as I mentioned above, it failed to invoke super().

If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.

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


What if I want the parent and child class to only have constructors with parameters?

Then the child class should always explicitly state what parent's constructor it wants to call.


Am I right to conclude that a parent class always needs a default or no-arg constructor?

No, it's fine to have a parent class without the default constructor as long as its children don't invoke super().

like image 22
Andrew Tobilko Avatar answered Sep 20 '22 16:09

Andrew Tobilko