Java 构造函数继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1644317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 18:37:09  来源:igfitidea点击:

Java Constructor Inheritance

javainheritanceconstructor

提问by Pablo Fernandez

I was wondering why in java constructors are not inherited? You know when you have a class like this:

我想知道为什么在java构造函数中没有继承?你知道当你有这样的课程时:

public class Super {

  public Super(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){
    this.serviceA = serviceA;
    //etc
  } 

}

Later when you inherit from Super, java will complain that there is no default constructor defined. The solution is obviously something like:

稍后当您从 继承时Super,java 会抱怨没有定义默认构造函数。解决方案显然是这样的:

public class Son extends Super{

  public Son(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){
    super(serviceA,serviceB,serviceC);
  }

}

This code is repetitive, not DRY and useless (IMHO)... so that brings the question again:

这段代码是重复的,不是 DRY 和无用的(恕我直言)......所以又带来了问题:

Why java doesn't support constructor inheritance? Is there any benefit in not allowing this inheritance?

为什么java不支持构造函数继承?不允许这种继承有什么好处吗?

采纳答案by Jon Skeet

Suppose constructors wereinherited... then because every class eventually derives from Object, everyclass would end up with a parameterless constructor. That's a bad idea. What exactly would you expect:

假设构造函数继承......然后,因为每个类最终从对象派生,类将结束与一个参数的构造函数。这是个坏主意。你究竟会期待什么:

FileInputStream stream = new FileInputStream();

to do?

去做?

Now potentially there should be a way of easily creating the "pass-through" constructors which are fairly common, but I don't think it should be the default. The parameters needed to construct a subclass are often different from those required by the superclass.

现在可能应该有一种方法可以轻松创建相当常见的“传递”构造函数,但我认为它不应该是默认值。构造子类所需的参数通常与超类所需的参数不同。

回答by David Santamaria

When you inherit from Super this is what in reality happens:

当您从 Super 继承时,实际上会发生以下情况:

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();
  }

}

So, that is the reason, because you have to call your unique constructor, since"Super" doesn't have a default one.

所以,这就是原因,因为您必须调用唯一的构造函数,因为“Super”没有默认构造函数。

Now, trying to guess why Java doesn't support constructor inheritance, probably because a constructor only makes sense if it's talking about concrete instances, and you shouldn't be able to create an instance of something when you don't know how it's defined (by polymorphism).

现在,试图猜测为什么 Java 不支持构造函数继承,可能是因为构造函数只有在谈论具体实例时才有意义,并且当你不知道它是如何定义的时候,你不应该能够创建它的实例(通过多态性)。

回答by Andrzej Doyle

Because constructors are an implementation detail - they're not something that a user of an interface/superclass can actually invoke at all. By the time they get an instance, it's already been constructed; and vice-versa, at the time you construct an object there's by definition no variable it's currently assigned to.

因为构造函数是一个实现细节——它们根本不是接口/超类的用户可以实际调用的东西。当他们得到一个实例时,它已经被构建了;反之亦然,在您构造一个对象时,根据定义,它当前没有分配给任何变量。

Think about what it would mean to force all subclasses to have an inherited constructor. I argue it's clearer to pass the variables in directly than for the class to "magically" have a constructor with a certain number of arguments just because it's parent does.

想想强制所有子类都有一个继承的构造函数意味着什么。我认为直接传递变量比让类“神奇地”拥有一个带有一定数量参数的构造函数更清晰,仅仅因为它是父类。

回答by Jonathan Feinberg

David's answer is correct. I'd like to add that you might be getting a sign from God that your design is messed up, and that "Son" ought not to be a subclass of "Super", but that, instead, Super has some implementation detail best expressed by havingthe functionality that Son provides, as a strategy of sorts.

大卫的回答是正确的。我想补充一点,你可能会从上帝那里得到一个信号,表明你的设计一团糟,“儿子”不应该是“超级”的子类,相反,超级有一些实现细节最好地表达通过拥有Son 提供的功能,作为一种策略。

EDIT: Jon Skeet's answer is awesomest.

编辑:Jon Skeet 的回答是最棒的。

回答by Rik

Constructors are not polymorphic.
When dealing with already constructed classes, you could be dealing with the declared type of the object, or any of its subclasses. That's what inheritance is useful for.
Constructor are always called on the specific type,eg new String(). Hypothetical subclasses have no role in this.

构造函数不是多态的。
在处理已经构造的类时,您可能正在处理对象的声明类型或其任何子类。这就是继承的用处。
构造函数总是在特定类型上调用,例如new String()。假设的子类在这方面没有作用。

回答by Michael Borgwardt

I don't know anylanguage where subclasses inherit constructors (but then, I am not much of a programming polyglott).

我不知道子类继承构造函数的任何语言(但是,我不是一个编程多语言者)。

Here'sa discussion about the same question concerning C#. The general consensus seems to be that it would complicate the language, introduce the potential for nasty side effects to changes in a base class, and generally shouldn't be necessary in a good design.

这是有关 C# 的相同问题的讨论。普遍的共识似乎是它会使语言复杂化,给基类中的更改带来潜在的不良副作用,并且在良好的设计中通常不需要。

回答by gustafc

Because constructing your subclass object may be done in a different way from how your superclass is constructed. You may not want clients of the subclass to be able to call certain constructors available in the superclass.

因为构造子类对象的方式可能与构造超类的方式不同。您可能不希望子类的客户端能够调用超类中可用的某些构造函数。

A silly example:

一个愚蠢的例子:

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

Or even simpler:

或者更简单:

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

From this example, you see that you'd need some way of declaring that "I want to inherit these constructors" or "I want to inherit all constructors except for these", and then you'd also have to specify a default constructor inheritance preference just in case someone adds a new constructor in the superclass... or you could just require that you repeat the constructors from the superclass if you want to "inherit" them, which arguably is the more obvious way of doing it.

从这个例子中,你看到你需要某种方式来声明“我想继承这些构造函数”或“我想继承除这些构造函数之外的所有构造函数”,然后你还必须指定一个默认的构造函数继承以防万一有人在超类中添加了一个新的构造函数......或者如果你想“继承”它们,你可以只要求你重复超类的构造函数,这可以说是更明显的方法。

回答by ChadNC

A derived class is not the the same class as its base class and you may or may not care whether any members of the base class are initialized at the time of the construction of the derived class. That is a determination made by the programmer not by the compiler.

派生类与其基类不是同一个类,您可能关心也可能不关心基类的任何成员在构造派生类时是否被初始化。这是由程序员而非编译器做出的决定。

回答by David R Tribble

Because a (super)class must have complete control over how it is constructed. If the programmer decides that it doesn't make sense to provide a default (no args) constructor as part of the class's contract, then the compiler should not provide one.

因为(超)类必须完全控制它的构造方式。如果程序员认为提供默认(无参数)构造函数作为类合同的一部分是没有意义的,那么编译器就不应该提供。

回答by clearlight

You essentially do inherit the constuctors in the sense that you can simply call super if and when appropriate, it's just that it would be error prone for reasons others have mentioned if it happened by default. The compiler can't presume when it is appropriate and when it isn't.

您本质上确实继承了构造函数,因为您可以在适当的时候简单地调用 super,只是由于其他人提到的默认情况下发生的原因,它很容易出错。编译器无法推测什么时候合适,什么时候不合适。

The job of the compiler is to provide as much flexibility as possible while reducing complexity and risk of unintended side-effects.

编译器的工作是提供尽可能多的灵活性,同时降低复杂性和意外副作用的风险。