我确定以前会问过这个问题,但是在搜索了一段时间后我找不到它。
我需要一个可以执行以下操作的函数:
public static AbstractClass createClass(Class<AbstractClass> theChildClass, int someVariable){
AbstractClass theInstance = theChildClass.newInstance(someVariable);
return theInstance;
}
然后在AbstractClass上我想像这样定义它:
public abstract class AbstractClass{
private int someVariable;
public AbstractClass(int someVariable){
this.someVariable = someVariable;
initOnChild();
}
protected abstract void initOnChild();
}
然后在子课上我理想地不想定义公共ChildClass(int someVariable){}&#34;方法,所以它们看起来像这样:
public class ChildClass extends AbstractClass{
@Override
protected void initOnChild(){
//do some stuff
}
}
我之后的理想结果是能够像这样调用方法:
ChildClass theInstance = UtilityClass.createClass(ChildClass.class, 1);
这甚至可能吗?任何解决方案或建议都非常赞赏。
答案 0 :(得分:1)
没有。构造函数不是继承的(因此不是JLS中的成员)。根据具体情况,您可能希望应用策略模式,比如说。
(ObNote:一般来说,从构造函数中调用可重写方法被认为是个坏主意,反射几乎总是一个非常糟糕的主意。)
答案 1 :(得分:0)
不,但有一个解决方案。
首先在构造函数中调用overriden方法的问题:
abstract class A {
A() {
init();
}
protected abstract void init();
}
class B extends A {
public String x = null;
public String y;
@Override
protected void init() {
x = "x";
y = "y";
}
}
public static void main(String[] args) {
B b = new B();
System.out.printf("x=%s, y=%s%n", b.x, b.y);
}
当然会给:
x=null, y=y
但是从表面上阅读并不明显,并且在基类中使用字段时,可能会变得不那么明显。
现在的解决方案。
由于您有静态工厂方法,可以将此方法放在AbstractClass中。然后它可以在构造之后调用init。
public static <T extends AbstractClass> T create(Class<T> childClass, int param) {
T instance = childClass.getConstructor().newInstance();
instance.init(param);
return instance;
}
这将执行默认构造函数。
如果这仍然不能令人满意,那么它可能只是某些数据结构不在正确的继承级别中,或者应该重新构建。