【发布时间】:2016-09-13 08:11:38
【问题描述】:
有几次我认为在 Java 中拥有可覆盖的构造函数会很好。
“可覆盖”表示构造逻辑可以在降级类中被覆盖和/或扩展,就像可以覆盖普通方法一样,即能够在子类之后调用父方法。
这个任务可以被表述为有一个方法,比如说,称为init(),它在构造时被调用,但只能在堆栈的最后一个构造函数中调用。
喜欢:
public class InitializationOverride {
public static class A {
A() {
System.out.println("Constructor of A");
}
void init() {
System.out.println("Init of A");
}
}
public static class B extends A {
B() {
System.out.println("Constructor of B");
}
@Override
void init() {
System.out.println("Init of B");
}
}
public static class C extends B {
C() {
System.out.println("Constructor of C");
}
@Override
void init() {
System.out.println("Init of C");
}
}
public static void main(String[] args) {
new A(); // should print "Constructor of A, Init of A"
new B(); // should print "Constructor of A, Constructor of B, Init of B"
new C(); // should print "Constructor of A, Constructor of B, Constructor of C, Init of C"
}
}
明显的方法是写
public static void main(String[] args) {
new A().init();
new B().init();
new C().init();
}
但这并不能保证init() 不会忘记调用。
有没有可能做点什么?
更新
在设计时不知道哪个类将是“最后一个”。预计将来会开发该类树。
更新 2
下面是反射和构造函数代码要求的解决方案,最后调用currentStage():
public class InitializationOverride {
public static class A {
A() {
System.out.println("Constructor of A");
currentStage(A.class);
}
void currentStage(Class<?> cls) {
if( cls == getClass() ) {
init();
}
}
void init() {
System.out.println("Init of A");
}
}
public static class B extends A {
B() {
System.out.println("Constructor of B");
currentStage(B.class);
}
@Override
void init() {
System.out.println("Init of B");
}
}
public static class C extends B {
C() {
System.out.println("Constructor of C");
currentStage(C.class);
}
@Override
void init() {
System.out.println("Init of C");
}
}
public static void main(String[] args) {
new A(); // should print "Constructor of A, Init of A"
new B(); // should print "Constructor of A, Constructor of B, Init of B"
new C(); // should print "Constructor of A, Constructor of B, Constructor of C, Init of C"
}
可以写得更简单吗?
【问题讨论】:
-
你没有说明为什么你认为这些方法应该被构造函数调用。
-
在
C构造函数中直接调用init有什么问题?将super.init();放入每个覆盖方法有什么问题? -
@defaultlocale 如果我将
init()放入C构造函数中,那么在构造A和B时将不会调用它。将super.init()放在任何地方都没有问题,但这有什么帮助呢? -
在构造函数中调用的覆盖方法是可能的,但它被认为是一个糟糕的设计,可能会导致一些问题,请参阅此问题以了解详细信息whats-wrong-with-overridable-method-calls-in-constructors
-
现在变得越来越复杂了。你能告诉我们这个设计背后的原因吗?此外,这个问题包含几个建议:stackoverflow.com/questions/27453105/…
标签: java inheritance constructor initialization