不能直接调用超类型构造函数 - 为什么不呢?

时间:2011-10-25 02:50:29

标签: java constructor

我在Java中有以下示例类:

public class A { }

public class Super {
    protected Super() { }
    public Super(A a) { }
}

public class Sub extends Super { }

public class Consumer {
    public Consumer() {
        Sub sub = new Sub(new A()); //compiler error
    }
}

编译器错误表明参数不能应用于Sub中的默认构造函数,这是完全可以理解的。

我很好奇的是这个决定背后的理由。 Java在Sub中生成默认的空构造函数;为什么不能在这种情况下在幕后调用呢?这主要是一个理智的手持,还是有技术原因?

编辑

我知道 这是一种语言限制。我很好奇为什么这是一种语言限制。

编辑2

似乎通常情况下,我太过接近我实际工作的代码,看看大局。我在下面的答案中发布了一个反例,说明了为什么这是BadThing®。

5 个答案:

答案 0 :(得分:2)

public class Sub extends Super { }

没有构造函数Sub(A a),它只有默认构造函数Sub()。

构造函数不是继承的。

答案 1 :(得分:2)

基类需要调用超级构造函数,以确保正确实例化对象。例如,考虑:

class Super {
   final String field1;

   public Super(String field1) {
      this.field1 = field1;
   }
   ...
}


class Base extends Super {
   final String field2;

   public Base(String field2) {
      this.field2 = field2;
   }
   ...
}

Base的构造函数是否会覆盖Super构造函数?如果是这样,则不再保证field1被初始化,使得继承的方法出乎意料地行为。

当您向子类添加非默认构造函数时,继承的构造函数将停止工作。我认为这是一个令人困惑且很少有用的功能,它被添加到语言中,虽然从技术上来说,我没有理由认为它不可能。

答案 2 :(得分:2)

我认为这是一个既可读性也不假设意图的问题。你说

  

Java生成默认的空构造函数;为什么不能在这种情况下在幕后调用呢?

然而对我而言,Java隐含地在幕后调用Super(A)构造函数“比调用Super()构造函数更加有意义,而忽略A

你有它。在这种情况下,我们已经有两个完全不同的假设(或可以)。

Java语言的核心原则之一是透明度。程序员应该尽可能地通过查看代码将会发生什么,有时以牺牲便利性或语法级别的 magic 为代价。

与此并行的原则并不是假设意图:在程序员的意图看似含糊不清的情况下,Java语言有时会支持编译错误,而不是通过某些(任意或其他)选择算法自动选择默认值。

答案 3 :(得分:0)

您已经覆盖了默认的公共构造函数,因此无法调用任何内容。

所以类Sub相当于

public class Sub extends Super
{
    protected Sub(){}
    public Sub(A a) { }
}

这是因为它的

  • Sane行为 - 按程序员的指示行事,也遵循OOP语言中的继承概念
  • 遵循其C ++遗产

答案 4 :(得分:0)

我将此作为此行为的技术原因;我同意其他几个答案,这可能在语义上令人困惑。

考虑以下示例:

public class A { }

public abstract class Super {
    protected Super() {
        // perform time consuming, destructive, or
        // otherwise one-time operations
    }

    public Super(A a) {
        this();
        // perform A-related construction operations
    }
}

public class Sub extends Super { }

public class Consumer {
    public Consumer() {
        Sub sub = new Sub(new A());
    }
}

构造Sub时,在这种情况下会调用Sub上的默认构造函数,它将链接到Super上的默认构造函数(因为这是语言定义的魔力) )。然后,对Super(A)的调用将调用在构造时设计为运行一次的逻辑。这显然不是开发人员想要的。

即使没有this()构造函数中的Super(A)调用,开发人员的意图也无法确定;由于某种原因,构造函数可能是互斥的。