如何打破超类构造链?

Keo*_*Kim 2 java inheritance class

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码产生以下结果:

ANIMAL CONSTRUCTOR 
Dog Constructor
Dog move
Run Code Online (Sandbox Code Playgroud)

似乎在创建dog实例时,它默认情况下也会调用Animal构造函数(隐式).

这很奇怪,因为我在考虑明确地打电话super()可以做同样的工作.

有没有办法打破这个构造函数链,让我的狗实例只调用Dog构造函数?

如果没有,是否有理由呢?

T.J*_*der 8

似乎在创建dog实例时,它默认情况下也会调用Animal构造函数(隐式).

是.

这很奇怪,因为我在考虑明确调用super()可以做同样的工作.

您可以,是的,但如果不这样做,编译器会super()在子类构造函数的开头插入一个对(没有args)的调用.允许您显式执行此操作的原因是您可能希望调用接受参数的超类构造函数.

有没有办法打破这个构造函数链,让我的dog实例只调用Dog构造函数?

没有.

如果没有,是否有理由呢?

因为Dog 是(n) Animal,所以Animal类必须有机会初始化Animal正在创建的对象的特定功能.

考虑:

class Animal {
    private Something useful;

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

class Dog extends Animal {
    private String breed;

    Dog(String breed) {
        this.breed = breed;
    }
}
Run Code Online (Sandbox Code Playgroud)

构造Dog实例时,在内存中它看起来像这样:

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

一个Dog实例是的精选通过定义什么是组合Animal的,什么是被定义的Dog.

现在,假设Animal从未调用过构造函数:useful会有什么价值?对!null(因为我将它声明为对象类型).但是Animal代码非常清楚地期望构造函数设置useful为有用的东西.如果我们能以某种方式绕过Animal构造函数,我们就会打破这个阶级.