Java 如何打破超类构造函数链?
上面的代码产生以下结果:Java 如何打破超类构造函数链?,java,class,inheritance,Java,Class,Inheritance,上面的代码产生以下结果: 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.pri
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();
}
}
似乎在创建dog实例时,默认情况下它也会调用Animal构造函数(隐式)
这很奇怪,因为我想显式调用super()
可以完成同样的工作
有没有办法打破这个构造函数链,让我的狗实例只调用狗构造函数
如果没有,原因是什么
似乎在创建dog实例时,默认情况下它也会调用Animal构造函数(隐式)
对
这很奇怪,因为我认为显式调用super()可以完成同样的工作
可以,是的,但是如果不可以,编译器会在子类构造函数的开头插入对super()
(不带参数)的调用。允许显式执行此操作的原因是,您可能希望调用接受参数的超类构造函数
有没有办法打破这个构造函数链,让我的狗实例只调用dog
constructor
没有
如果没有,原因是什么
因为Dog
是一个(n)Animal
,因此Animal
类必须有机会初始化所创建对象的Animal
特定特征
考虑:
ANIMAL CONSTRUCTOR
Dog Constructor
Dog move
当您构造一个Dog
实例时,在内存中它看起来是这样的:
class Animal {
private Something useful;
Animal() {
this.useful = /*...something useful...*/;
}
}
class Dog extends Animal {
private String breed;
Dog(String breed) {
this.breed = breed;
}
}
+-------------+
|狗|
+-------------+
|有用:|
|品种:|
+-------------+
Dog
实例是由Animal
定义的内容和Dog
定义的内容的组合
现在,假设从未调用过
Animal
的构造函数:有什么有用的值?对!null
(因为我将其声明为对象类型)。但是Animal
的代码非常清楚地期望构造函数将设置为有用的东西。如果我们能够以某种方式绕过Animal
的构造函数,我们将破坏类。在实例化子类时,无法阻止调用Animal
构造函数。本质上,这是因为基类可能也包含需要设置的字段
(请注意,隐式基类java.lang.Object
的构造函数也被调用。您的问题更多的是关于继承继承继承权中某个地方的“缺少构造函数”)
如果Animal
不包含任何字段,则可以将其设置为接口。那么它就没有构造函数了。以这种方式使用接口允许您在非动物对象(如车辆)上定义类似于移动的方法。然后,您将遇到一个称为composition的编程范例。我认为这可能是一个XY问题。为什么您不希望调用Animal
构造函数呢?“为什么”将这个问题与最初标识为重复的问题区分开来。也就是说,几乎可以肯定的是,这个问题的早期版本是可以关闭并指向的。这个问题大部分(完全?)是通过结合来回答的。因此super()
被用来明确它是继承的,或者是从许多其他构造函数中选择的?@KeonKim:是的super()
(字面意思,没有参数)纯粹是风格问题。举例来说,我总是这样做,正是因为这些原因:为了弄清楚发生了什么,特别是我称之为无参数版本。但有些人相当合理地认为我不应该这样做,因为编译器总是这样做,所以他们发现看到它显式编写时会感到不舒服。当您调用super(with,args,here)
时,这当然是必需的,因为编译器永远不会为您这样做。(即使超类没有无参数构造函数也不行。)
+-------------+
| Dog |
+-------------+
| useful: ... |
| breed: ... |
+-------------+