Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to break super class constructor chain?

class Animal {
    protected Animal(){
        System.out.println("ANIMAL CONSTRUCTOR");
    }
    public void move(){
        System.out.println("ANIMAL Move");
    }
}

class Dog extends Animal{
    public Dog(){
        System.out.println("Dog Constructor");
    }
    public void move(){
        System.out.println("Dog move");
    }

}


public class Test {
    public static void main(String args[]){
    Dog d = new Dog();
    d.move();
    }
}

The code above yields the result below:

ANIMAL CONSTRUCTOR 
Dog Constructor
Dog move

It seems that when dog instance is created, it also calls Animal constructor by default (implicitly).

Which is strange because I was thinking explicitly calling super() can do the same job.

Is there any way to break this constructor chain and let my dog instance only call Dog constructor?

if there is not, is there reason for it?

like image 741
Keon Kim Avatar asked Dec 20 '25 17:12

Keon Kim


1 Answers

It seems that when dog instance is created, it also calls Animal constructor by default (implicitly).

Yes.

Which is strange because I was thinking explicitly calling super() can do the same job.

You can, yes, but if you don't, the compiler inserts a call to super() (with no args) at the beginning of your subclass constructor. The reason for allowing you to do it explicitly is that you may want to call a superclass constructor that accepts arguments.

Is there any way to break this constructor chain and let my dog instance only call Dog constructor?

No.

if there is not, is there reason for it?

Because Dog is a(n) Animal, and so the Animal class must have its chance to initialize the Animal-specific features of the object being created.

Consider:

class Animal {
    private Something useful;

    Animal() {
        this.useful = /*...something useful...*/;
    }
}

class Dog extends Animal {
    private String breed;

    Dog(String breed) {
        this.breed = breed;
    }
}

When you construct a Dog instance, in memory it looks like this:

+-------------+
|     Dog     |
+-------------+
| useful: ... |
| breed:  ... |
+-------------+

A Dog instance is a combination of what's defined by Animal and what's defined by Dog.

Now, suppose Animal's constructor were never called: What value would useful have? Right! null (because I declared it as an object type). But Animal's code quite clearly expects the constructor to set useful to something useful. If we could somehow bypass Animal's constructor, we'd be breaking the class.

like image 61
T.J. Crowder Avatar answered Dec 22 '25 06:12

T.J. Crowder



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!