2

考虑

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 的构造函数不同的签名构造函数?为什么我们必须首先调用超类的构造函数?

4

3 回答 3

2

可以定义具有不同签名的构造函数。但是在子类的构造函数中,你必须调用基类的构造函数。基类需要初始化自己(例如它的私有成员),除了调用它的构造函数之一之外没有其他方法可以做到这一点。

于 2013-09-29T16:50:41.333 回答
1

为什么我们不能用与 MyClass 的构造函数不同的签名来定义 MyExtendedClass 的构造函数?

你当然可以做到。您得到的错误是出于不同的原因。

为什么我们必须首先调用超类的构造函数?

因为这就是你的类的对象被初始化的方式。对象的状态包括它自己的类中的所有字段,以及所有超类的所有非静态字段。

因此,当您创建一个实例时,应该为所有超类初始化状态,然后最终初始化它自己的类。这就是为什么构造函数的第一条语句应该super()链接到超类构造函数,或者this()链接到它自己的类构造函数。

您的代码可能失败的原因是,您正在尝试使用字符串参数调用超类构造函数。但是目前没有这样的构造函数。超类只有一个带有参数的构造int函数。此外,添加super()也不起作用。因为您的超类没有 0-arg 构造函数。

尝试将您的构造函数更改为:

public MyExtendedClass(SomeType s){ 
    super(0);  
}

它会起作用的。或者,为您的超类添加一个 0 参数构造函数,并保持子类构造函数不变。在这种情况下它也可以工作。


推荐阅读:

于 2013-09-29T16:50:49.177 回答
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);
}
于 2013-09-29T18:10:35.407 回答