java 跳过父构造函数调用祖父母的
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1878558/
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
Jump over parent constructor to call grandparent's
提问by German
The problem is this: I have an abstract class that does some work in its constructor, and a set of child classes that implement the abstract class:
问题是这样的:我有一个抽象类,它在其构造函数中做了一些工作,以及一组实现抽象类的子类:
class AbstractClass {
AbstractClass(){ /* useful implementation */ }
}
class ConcreteClass1 extends AbstractClass {
ConcreteClass1(){ super(); /* useful implementation */ }
}
Then, the concrete classes need to be customized and one solution is to extend the concrete classes:
然后,需要自定义具体类,一种解决方案是扩展具体类:
class CustomizedClass1 extends ConcreteClass1 {
CustomizedCLass1(){ super(); /* useful implementation */ }
}
BUT the problem is that the customized classes need only to call the abstract class's constructor and not the concrete class's constructor.
但问题是定制类只需要调用抽象类的构造函数,而不是具体类的构造函数。
How do you achieve this? Suggestions to change the class's relationships are valid.
你是如何做到这一点的?更改班级关系的建议是有效的。
EDIT: The concrete example is that ConcreteClass1 and CustomizedClass1 have different sets of data (ConcreteData1 and CustomizedData1), and it is retrieved from the database in the class's constructor. The problem is that creating an instance of CustomizedClass1 will retrieve both data entities.
编辑:具体的例子是 ConcreteClass1 和 CustomizedClass1 有不同的数据集(ConcreteData1 和 CustomizedData1),它是从类的构造函数中的数据库中检索的。问题是创建 CustomizedClass1 的实例将检索两个数据实体。
I am aware that using simple inheritance it's probably not the best thing to do, that's why I pointed out that suggestions to change the class's relationships are valid.
我知道使用简单继承可能不是最好的做法,这就是为什么我指出更改类关系的建议是有效的。
采纳答案by MattMcKnight
Easy (but why?):
简单(但为什么?):
class AbstractClass {
AbstractClass(){ /* useful implementation */ }
}
class ConcreteClass1 extends AbstractClass {
ConcreteClass1(){ super(); /* useful implementation */ }
ConcreteClass1(boolean skip){ super(); }
}
class CustomizedClass1 extends ConcreteClass1 {
CustomizedCLass1(){ super(true); /* useful implementation */ }
}
回答by TofuBeer
You cannot do this in Java. I frequently have students who want to do this, but I have never seen a case where it is really what they wanted to do.
您不能在 Java 中执行此操作。我经常有学生想要这样做,但我从未见过真正他们想做的事情。
Can you give a concrete example of what it is you want to do and why (your description is too vague) and I am sure a solution can be achieved :-)
你能举一个具体的例子来说明你想要做什么以及为什么(你的描述太模糊了)我相信可以实现一个解决方案:-)
Edit:
编辑:
For a real world example of why you do not want to do this (normally) would be a hierarchy like:
对于为什么您不想这样做(通常)的真实世界示例,将是如下层次结构:
Animal (constructor makes the eyes)
|
Mammal (constructor makes the lungs)
|
Human (constructor sets the language)
If the Human constructor could skip over the Mammal constructor then you would wind up with a Human who has no lungs... not very useful.
如果 Human 构造函数可以跳过 Mammal 构造函数,那么您最终会得到一个没有肺的 Human ……不是很有用。
回答by Wyzard
Any instance of CustomizedClass1is also an instance of ConcreteClass1, by definition, so it mustbe constructed as a valid ConcreteClass1instance before the CustomizedClass1constructor can run. Otherwise, what would happen if you called ConcreteClass1methods on it? They'd be trying to operate on variables that haven't been initialized yet.
根据定义, 的任何实例CustomizedClass1也是 的实例ConcreteClass1,因此必须将其构造为有效ConcreteClass1实例,然后CustomizedClass1构造函数才能运行。否则,如果你ConcreteClass1在它上面调用方法会发生什么?他们会尝试对尚未初始化的变量进行操作。
If you think you need to do this, chances are your design needs re-thinking. If you only want some of the functionality from ConcreteClass1, for example, that functionality could be factored out into a superclass of ConcreteClass1, and CustomizedClass1could extend that to get just the functionality that it needs.
如果您认为需要这样做,那么您的设计很可能需要重新思考。ConcreteClass1例如,如果您只想要 的某些功能,则可以将该功能分解为 的超类ConcreteClass1,并且CustomizedClass1可以扩展它以获得它需要的功能。
Please provide more information about the relationship between these classes.
请提供有关这些类之间关系的更多信息。
回答by julian_t
Two comments: Firstly, you're not supposed to think in terms of 'jumping over' constructors like this. Secondly, it reallysounds like you need to rethink your class relationships.
两条评论:首先,您不应该像这样考虑“跳过”构造函数。其次,听起来你真的需要重新考虑你的阶级关系。
Any time you find yourself thinking "A extends B, except that..." is a very good time to look at things further. 'Extends' implies 'is a', which is an either/or relationship: having optional behaviour adds grey areas which will bite you later on.
任何时候你发现自己在想“A 扩展了 B,除了……”是进一步审视事物的好时机。“扩展”暗示“是一个”,这是一种非此即彼的关系:具有可选行为会增加灰色区域,这些区域稍后会咬你。
As people have said, you could provide multiple constructors on ConcreteClass1 to do the initialization you require in each case, maybe making them protected so that they can only be used by subclasses. But here's a question: what if someone wants to write CustomizedClass2 that needs some (but not all) of the functionality in ConcreteClass1? Do you add another custom constructor?
正如人们所说,您可以在 ConcreteClass1 上提供多个构造函数来执行每种情况下所需的初始化,也许可以使它们受到保护,以便它们只能由子类使用。但这里有一个问题:如果有人想要编写需要 ConcreteClass1 中的某些(但不是全部)功能的 CustomizedClass2 怎么办?您是否添加了另一个自定义构造函数?
回答by user401321
Is CustomizedData1 a subclass of ConcreteData1? If so, then I would suggest having a (possibly protected) constructor for ConcreteClass1 that takes in a ConcreteData1 to use instead of fetching its own during initialization. This way, CustomizedClass1 can fetch its CustomizedData1 and pass it to its call to super. Unfortunately this may be tricky or fairly impossible if you can't fetch the data prior to some internal init.
CustomizedData1 是 ConcreteData1 的子类吗?如果是这样,那么我建议为 ConcreteClass1 使用一个(可能受保护的)构造函数,它接受一个 ConcreteData1 来使用,而不是在初始化期间获取它自己的构造函数。这样,CustomizedClass1 可以获取它的 CustomizedData1 并将它传递给它对 super 的调用。不幸的是,如果您无法在某些内部初始化之前获取数据,这可能会很棘手或相当不可能。
class ConcreteClass1 extends AbstractClass {
ConcreteClass1(){
this(...fetch data as before...);
}
ConcreteClass1(ConcreteData1 data){
myData = data;
...
}
}
class CustomizedClass1 extends ConcreteClass1 {
CustomizedCLass1(){
super(new CustomizedData1(...));
...
}
}
But then CustomizedClass1 probably needs a reference to the data as a CustomizedData1 not merely a ConcreteData1. It could just typecast its inherited ConcreteData1 all the time, but that seems yucky. But if it stores its own reference to the data, then there is a need to keep the references in sync if they're not final.
但是,CustomizedClass1 可能需要将数据引用为 CustomizedData1,而不仅仅是 ConcreteData1。它可以一直对它继承的 ConcreteData1 进行类型转换,但这看起来很糟糕。但是如果它存储自己对数据的引用,那么如果引用不是最终引用,则需要保持同步。
回答by rynmrtn
This sounds to me like a mixture of concerns - something Java is not well equipped to handle.
在我看来,这听起来像是混合的问题——Java 无法很好地处理这些问题。
While it is not the answer you were hoping for or one that I am proud to type, you could simply create ConcreteClass2that mimics ConcreteClass1and uses the AbstractClass's constructor.
虽然这不是您希望的答案,也不是我引以为豪的答案,但您可以简单地创建ConcreteClass2模仿ConcreteClass1并使用AbstractClass的构造函数。
As @TofuBeer said, this is not something that Java supports. This is why some modern languages (i.e. Scala w/ Traits) are gaining passionate developers.
正如@TofuBeer 所说,这不是 Java 支持的。这就是为什么一些现代语言(即带有 Traits 的 Scala)吸引了热情的开发人员的原因。
回答by mlvljr
Why not just actually customize a newly-created ConcreteClass1instance to behave like an AbstractClassinstance (provided that ConcreteClass1has corresponding protected methods just for that)? I.e.:
为什么不直接自定义一个新创建的ConcreteClass1实例以使其表现得像一个AbstractClass实例(前提是ConcreteClass1具有相应的保护方法)?IE:
class AbstractClass {
public AbstractClass() { /* useful implementation */ }
}
class ConcreteClass1 extends AbstractClass {
public ConcreteClass1() {
/* A hidden super() call put here by the compiler. */
/* Useful implementation */
}
protected void customize_with(SomeParams customization_params) {
/*
Customize this ConcreteClass1 instance according to parameters
passed. As a result, the instance behavior will 'revert' (in the
way you need it) to that of an AbstractClass instance.
*/
}
}
class CustomizedClass1 extends ConcreteClass1 {
public CustomizedCLass1() {
/* A hidden super() call put here by the compiler. */
customize_with(customization_params);
/* Rest of useful implementation */
}
}
The design intentions and logic here may be as follows:
这里的设计意图和逻辑可能如下:
You want to get the (basic) behavior of
ConcreteClass1via inheritance, you inherit from it (this of course imposes designing it worth inheriting from).You would like to customize the behavior provided by
ConcreteClass1by default. The customization you would like to achieve can usually be described with some parameters. Just pass these parameters to a special method of theCustomizedClass1(which can be protected), and name itcustomize()accordingly.The customization performed in the
ConcreteClass1()constructor can be any, specifically, the class instance behavior can be 'reverted' to that ofAbstractClass, which you are probably asking for (if I get it right).Calling
customize_with()may actually introduce some overhead depending on the actual stuff done inConcreteClass1(), in this case using overloaded (and possibly protected) constructors is definitely a better solution, unless you would likeConcreteClass1' instances to be dynamically customizable (in which casecustomize_with()and probably the rest ofConcreteClass1should be designed accordingly i.e. supporting such behavior by contract).
你想获得
ConcreteClass1通过继承的(基本)行为,你从它继承(这当然强加了值得继承的设计)。您想自定义
ConcreteClass1默认提供的行为。您想要实现的定制通常可以用一些参数来描述。只需将这些参数传递给CustomizedClass1(可以保护的)的特殊方法,并相应地命名customize()。在
ConcreteClass1()构造函数中执行的自定义可以是任何,具体来说,类实例行为可以“恢复”到AbstractClass您可能要求的行为(如果我做对了)。调用
customize_with()实际上可能会引入一些开销取决于实际要做的东西ConcreteClass1(),在这种情况下使用重载的(也可能是受保护的)构造绝对是一个更好的解决办法,除非你想ConcreteClass1“的实例是动态可定制(在这种情况下customize_with(),可能剩下的ConcreteClass1应相应地设计,即通过合同支持此类行为)。
Excuse me if anything's wrong with the syntax (I have not written much Java code).
如果语法有问题,请见谅(我没有写太多 Java 代码)。
回答by Mehboob
Yes you can tweak! Add another method to parent class(B) and in your Child class(C) call it as super.executeParentA(); in this method call super.execute()
是的,你可以调整!将另一个方法添加到父类(B)并在您的子类(C)中将其称为 super.executeParentA(); 在这个方法中调用 super.execute()
A --> execute()
B --> executeParent_A() { super.execute(); }
C --> super.executeParent_A();
-Mehboob
-Mehboob
回答by zakmck
I can think of two cases where one might want to do this (actually not):
我可以想到两种可能想要这样做的情况(实际上不是):
Case 1, ConcreteClass2 runs shared initialisation from the top class, but then does its own initialisation sequence, which is different/conflicts than the one in ConcreteClass1 -> have an init () method and override it (instead of attempting to override the ConcreteClass1's constructor).
情况 1,ConcreteClass2 从顶级类运行共享初始化,然后执行自己的初始化序列,这与 ConcreteClass1 中的不同/冲突 -> 有一个 init() 方法并覆盖它(而不是尝试覆盖 ConcreteClass1 的构造函数)。
Case 2, you have polymorphic initialisation of one (or more) class member (this is actually a specific case of the previous one):
情况 2,您对一个(或多个)类成员进行了多态初始化(这实际上是前一个的特定情况):
public class ConcreteClass1 extend AbstractClass
{
protected F1 f;
public ConcreteClass1 () {
super ();
this.f = new F1();
}
}
public ConcreteClass2 extends ConcreteClass1
{
public ConcreteClass2 () {
super (); // I'd like to do super.super() instead (no, you don't)
this.f = new F2(); // We wasted time with new F1 ();
}
}
In such case, either use the init() approach, or do this:
在这种情况下,要么使用 init() 方法,要么这样做:
protected ConcreteClass1 ( F1 f ) {
super ();
this.f = f;
}
public ConcreteClass1 () {
this ( new F1 () );
}
...
public ConcreteClass2 () {
super ( new F2 () );
}
In other words, make the reason for the jump explicit, for implicitly jumping over the hierarchy is forbidden and for the good reasons explained in other answers.
换句话说,明确跳转的原因,禁止隐式跳过层次结构,以及其他答案中解释的充分理由。
回答by German
One way I came up with:
我想出的一种方法:
class AbstractClass {
AbstractClass(){ init(); }
protected init(){ /* useful implementation */ }
}
class ConcreteClass1 extends AbstractClass {
ConcreteClass1(){ init(); /* useful implementation */ }
}
class CustomizedClass1 extends ConcreteClass1 {
CustomizedCLass1(){ init(); /* useful implementation */ }
}
In this way, CustomizedClass1 gets the behavior it needs from AbstractClass without passing through ConcreteClass1 initializations.
这样,CustomizedClass1 从 AbstractClass 获取它需要的行为,而无需通过 ConcreteClass1 初始化。
EDIT: Ouch, this doesn't work because the parent's constructors are implicitly called as one of the commenters pointed out, I think the easy way is to have different constructors.
编辑:哎呀,这不起作用,因为正如评论者之一指出的那样,父的构造函数被隐式调用,我认为简单的方法是使用不同的构造函数。

