子类型的构造函数

时间:2013-09-29 16:44:36

标签: java inheritance constructor

考虑

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

3 个答案:

答案 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);
}