java Java构造函数扩展
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10675076/
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
Java constructor extending
提问by ShadowPrince
When I extend some class,for example:
当我扩展某个类时,例如:
public class First {
int id;
public First(int _id) {
id = _id;
}
}
and
和
public class Second extends First {
}
I must redeclare the constructor for Second class, when I just need to do the same. I can:
当我只需要做同样的事情时,我必须重新声明 Second class 的构造函数。我能:
public Second(int _id) {
super(_id);
}
But every time I change the parent constructor all of the extended classes' constructors need to be edited.
但是每次我更改父构造函数时,都需要编辑所有扩展类的构造函数。
How can I extend the constructor fully?
如何完全扩展构造函数?
Damn, don't tell me about phone and antenna, I have used OOP many times.
该死的,别跟我说电话和天线,我用过很多次OOP。
Now I only ask - can't I write public Class(){} on extended classes, and use the parent constructor?
现在我只问 - 我不能在扩展类上编写 public Class(){} 并使用父构造函数吗?
It seems that I can't. Okay.
我好像不能 好的。
回答by Ted Hopp
When you define a subclass, it does not inherit constructors from the superclass. For anything other than the default superclass constructor, you need to explicitly call a superclass constructor in each subclass constructor. (That means, among other things, that if the base class does not have a default constructor, neither can any child classevery child class constructor must explicitly call a superclass constructor—and no child class can have simply a compiler-generated default constructor. There's one exception to this; see [*]below.)
定义子类时,它不会从超类继承构造函数。对于默认超类构造函数以外的任何内容,您需要在每个子类构造函数中显式调用超类构造函数。(这意味着,除其他外,如果基类没有默认构造函数,那么每个子类构造函数的任何子类都不能显式调用超类构造函数——并且没有子类可以具有简单的编译器生成的默认构造函数。对此有一个例外;请参阅下面的[*]。)
Inheriting constructors could cause all sorts of problems. Imagine something like this:
继承构造函数可能会导致各种问题。想象一下这样的事情:
class Base {
private int mId;
public Base(int id) {
mId = id;
}
. . .
}
Now we want to derive a class that has a second attribute—a tag—that we want to ensure is never null
. So we write the following:
现在我们想要派生一个具有第二个属性(一个标签)的类,我们希望确保它是 never null
。所以我们写如下:
class Derived extends Base {
private Object mTag;
public Derived(Object tag, int id) {
super(id);
if (tag == null) {
throw new IllegalArgumentException("tag cannot be null");
}
mTag = tag;
}
. . .
}
Now imagine constructing an instance of Derived
like this:
现在想象构建一个这样的实例Derived
:
Derived derived = new Derived(3);
If constructors were inherited, this would presumably be legal. What would it mean? For one thing, mTag
would be set to its default value of null
. There would be no way for Derived
to enforce the rule that all instances of Derived
must have a non-null tag.
如果构造函数是继承的,这大概是合法的。这意味着什么?一方面,mTag
将设置为其默认值null
。没有办法Derived
强制执行所有实例都Derived
必须具有非空标记的规则。
At the cost of requiring a bit more typing, Java rules out inheriting constructors precisely to allow each class to fully control how its instances get created.
以需要更多类型为代价,Java 排除了继承构造函数的可能性,以允许每个类完全控制其实例的创建方式。
[*]There's one case where the compiler will automatically generate a non-default constructor. Consider the Base
class above and this code:
[*]在一种情况下,编译器会自动生成一个非默认构造函数。考虑Base
上面的类和这段代码:
Base foo = new Base(3) {
. . . // some extended functionality
};
Now foo
is being initialized to an anonymous subclass of Base
. For ease of reference, let's call this subclass Base$Anon
. The compiler will generate code equivalent to:
现在foo
正在被初始化为 的匿名子类Base
。为了便于参考,我们称这个子类为Base$Anon
。编译器将生成等效于以下内容的代码:
class Base$Anon extends Base {
Base$Anon(int id) {
super(id);
}
. . . // some extended functionality
}
Base foo = new Base$Anon(3);
This is the only case where the compiler generates a non-default constructor if you don't specify any constructors of your own. In fact, the language syntax doesn't even let you declare a constructor for an anonymous class; you must rely on the compiler generating one for you.
如果您不指定任何自己的构造函数,这是编译器生成非默认构造函数的唯一情况。事实上,语言语法甚至不允许您为匿名类声明构造函数;您必须依靠编译器为您生成一个。
回答by Alexander Torstling
This limitation is one of the reasons why I prefer composition over inheritance. Consider using code like this instead:
这种限制是我更喜欢组合而不是继承的原因之一。考虑使用这样的代码:
public class Second {
private final First first;
public Second(final First first) {
this.first=first;
}
public int getId() {
return first.getId();
}
}
This construct also leaves your two classes less coupled and makes the relation between the classes clearer in my opinion. For a more thorough discussion of composition over inheritance, see for instance this question: Prefer composition over inheritance?
在我看来,这种结构还使您的两个类不那么耦合,并使类之间的关系更加清晰。有关组合而不是继承的更深入讨论,请参见例如这个问题:更喜欢组合而不是继承?