考虑
class MyClass{
public MyClass(Integer i){}
}
class MyExtendedClass extends MyClass{
public MyExtendedClass(SomeType s){ ... }//Compile error if SomeType!=Integer
public MyExtendedClass(Integer i){
super(i);
...
}
}
为什么我们不能定义MyExtendedClass
的构造函数,其签名与MyClass的构造函数不同?为什么我们必须首先调用超类的构造函数?
答案 0 :(得分:2)
你可以定义具有不同签名的构造函数。但是在子类的构造函数中,必须调用基类的构造函数。基类需要初始化自己(例如它的私有成员),除了通过调用其构造函数之外,没有其他方法可以执行此操作。
答案 1 :(得分:1)
为什么我们不能使用与MyClass的构造函数不同的签名来定义MyExtendedClass的构造函数?
你当然可以这样做。你得到的错误是出于其他原因。
为什么我们必须首先调用超类的构造函数?
因为这就是你的类的对象被初始化的方式。对象的状态包含它自己的类中的所有字段,以及所有超类的所有非静态字段。
因此,在创建实例时,应该为所有超类初始化状态,然后最终为其自己的类初始化状态。这就是为什么构造函数的第一个语句应该super()
链接到超类构造函数,或者this()
链到它自己的类构造函数。
您的代码可能失败的原因是,您尝试使用字符串参数调用超类构造函数。但目前没有这样的构造函数。超类只有一个构造函数采用int
参数。此外,添加super()
也不会起作用。因为你的超类没有0-arg构造函数。
尝试将构造函数更改为:
public MyExtendedClass(SomeType s){
super(0);
}
它会起作用。或者,在超类中添加一个0参数构造函数,并保留子类构造函数。在这种情况下它也会起作用。
建议阅读:
答案 2 :(得分:0)
您的构造函数可以具有不同的签名。但是你必须调用一个超级构造函数。这就是Java的工作原理,请参阅Java语言规范。
备选方案1:您可以调用静态方法,如下所示:
public MyExtendedClass(SomeType s){ super(convertToInt(s)); }
private Integer convertToInt(SomeType st){ ... }
备选方案2:使用组合/委托而不是继承。
class MyExtendedClass [
private MyClass delegate;
public MyExtendedClass(SomeType s){
do what you want
delegate = new MyClass(...);
}
public void doSomething(... params){
delegate.doSomething(params);
}