Java构造函数inheritance
我想知道为什么在Java构造函数不被inheritance? 你知道什么时候你有这样的一个class级:
public class Super { public Super(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){ this.serviceA = serviceA; //etc } }
后来当你从Super
inheritance时,java会抱怨没有定义默认的构造函数。 解决scheme显然是这样的:
public class Son extends Super{ public Son(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){ super(serviceA,serviceB,serviceC); } }
这个代码是重复的,而不是干燥和无用的(恕我直言)…所以再次提出的问题:
为什么java不支持构造函数inheritance? 不允许这种inheritance有什么好处吗?
假设构造函数是inheritance的…然后因为每个类最终都是从Object派生的,所以每个类最终都会有一个无参数的构造函数。 这是一个坏主意。 你会期待什么:
FileInputStream stream = new FileInputStream();
去做?
现在可能应该有一种方法来轻松创build相当常见的“传递”构造函数,但我不认为它应该是默认的。 构造子类所需的参数通常与超类所要求的不同。
当你从Superinheritance的时候,这就是事实:
public class Son extends Super{ // If you dont declare a constructor of any type, adefault one will appear. public Son(){ // If you dont call any other constructor in the first line a call to super() will be placed instead. super(); } }
所以,这就是原因,因为你必须调用你的唯一构造函数,因为“Super”没有缺省的构造函数。
现在,试图猜测为什么Java不支持构造函数inheritance,可能是因为构造函数只有在讨论具体实例时才有意义,而当你不知道它是如何定义的时候,你不应该创build一个实例(通过多态性)。
因为构build你的子类对象可能是以不同于你的超类构造的方式完成的。 您可能不希望子类的客户端能够调用超类中可用的某些构造函数。
一个愚蠢的例子:
class Super { protected final Number value; public Super(Number value){ this.value = value; } } class Sub { public Sub(){ super(Integer.valueOf(0)); } void doSomeStuff(){ // We know this.value is an Integer, so it's safe to cast. doSomethingWithAnInteger((Integer)this.value); } } // Client code: Sub s = new Sub(Long.valueOf(666L)): // Devilish invocation of Super constructor! s.doSomeStuff(); // throws ClassCastException
甚至更简单:
class Super { private final String msg; Super(String msg){ if (msg == null) throw new NullPointerException(); this.msg = msg; } } class Sub { private final String detail; Sub(String msg, String detail){ super(msg); if (detail == null) throw new NullPointerException(); this.detail = detail; } void print(){ // detail is never null, so this method won't fail System.out.println(detail.concat(": ").concat(msg)); } } // Client code: Sub s = new Sub("message"); // Calling Super constructor - detail is never initialized! s.print(); // throws NullPointerException
从这个例子中,你会发现你需要某种方式来声明“我想inheritance这些构造函数”或“我想inheritance除这些构造函数之外的所有构造函数”,然后你还必须指定一个默认的构造函数inheritance如果有人在超类中添加一个新的构造函数,或者如果你想“inheritance”它们,你可以只需要重复超类的构造函数,这可以说是更明显的方法。
因为构造函数是一个实现细节 – 它们不是一个接口/超类的用户实际上可以调用的东西。 当他们得到一个实例时,它已经被构build了; 反之亦然,在你构build一个对象的时候,根据定义,它没有当前赋值的variables。
想一想强制所有的子类有一个inheritance的构造函数意味着什么。 我认为,直接传递variables比类更明确,“神奇地”拥有一个具有一定数量的参数的构造函数,因为它是父类的。
构造函数不是多态的。
在处理已经构build的类时,可以处理对象的声明types或其任何子类。 这就是inheritance是有用的。
构造函数总是调用特定的types,例如new String()
。 假设的子类在这方面没有任何作用。
大卫的回答是正确的。 我想补充一点,你可能会从上帝那里得到一个标志,说明你的devise是混乱的,而“儿子”不应该是“超级”的子类,而是超级具有最佳expression的实现细节通过具有 Son提供的function,作为各种策略。
编辑:Jon Skeet的答案是最好的。
没有一个令人信服的答案。
每个问题你会()将与构造函数inheritance你已经有其他方法。 如果你的inheritance类有一个错误,那么就有一个错误。 戏剧…
这些stream行的“传递构造函数”真的很烦人的废话。 我讨厌JAVA不断强迫我只是出于宗教原因写愚蠢的代码…
因为一个(超)类必须完全控制它的构造。 如果程序员决定提供一个默认的(没有args)构造函数作为类的契约的一部分是没有意义的,那么编译器不应该提供一个。
你基本上是inheritance了这个构造函数,你可以简单的调用super,只要在适当的时候调用super就可以了。 编译器不能推测什么时候合适,什么时候不合适。
编译器的工作是提供尽可能大的灵活性,同时降低复杂性和意外副作用的风险。
我不知道任何语言的子类inheritance构造函数(但是,我不是一个编程polyglott)。
以下是关于C#相同问题的讨论。 普遍的共识似乎是这会使语言复杂化,给基级的变化带来可怕的副作用,而且在一个好的devise中通常不是必须的。
派生类与其基类不是同一个类,您可能会也可能不会在构造派生类时是否初始化基类的任何成员。 这是程序员不是由编译器做出的决定。