Java 在超类构造函数中调用抽象方法
我在super的构造函数中有一个抽象方法调用。我遇到错误“构造函数调用必须是构造函数中的第一条语句”,因为在调用super的构造函数之前,我需要初始化子类中的某些状态 我知道构造函数调用必须是第一个。。但这让我有些问题 我的超类中有一个抽象方法,所有子类都实现自己。 但是子类构造函数需要在运行抽象方法之前必须处理的参数 在我的代码中,我在超类构造函数中使用了抽象方法,因此您当然会理解这个问题: 超级课堂:Java 在超类构造函数中调用抽象方法,java,superclass,Java,Superclass,我在super的构造函数中有一个抽象方法调用。我遇到错误“构造函数调用必须是构造函数中的第一条语句”,因为在调用super的构造函数之前,我需要初始化子类中的某些状态 我知道构造函数调用必须是第一个。。但这让我有些问题 我的超类中有一个抽象方法,所有子类都实现自己。 但是子类构造函数需要在运行抽象方法之前必须处理的参数 在我的代码中,我在超类构造函数中使用了抽象方法,因此您当然会理解这个问题: 超级课堂: 使用super(i1,i2)获取info1和info2 通过子类执行抽象方法 但是,超类构
abstract public class Prylar {
abstract public Integer value();
private String itemName;
private Person owner;
public Prylar(Person thisOwner, String iN){
owner = thisOwner;
itemName = iN;
value = value();
}
public class Smycken extends Prylar{
private int antalStenar;
private boolean guldEllerSilver;
private int value;
public Smycken (Person who, String n, int aS, boolean material){
super(who,n);
antalStenar = aS;
guldEllerSilver = material;
}
public Integer value() {
if (guldEllerSilver){
value = 2000;
}
else{
value= 700;}
value += (500*antalStenar);
return value;
}
}
最后,我想对大家说声谢谢,感谢你们花时间阅读并帮助一个人走出困境。我真的很感激。希望当其他人有类似的问题时,他们会偶然发现这一点
谢谢大家 您面临的问题是,当您从基类调用抽象(或任何重写)方法时,子类实例没有完全构造。确保对象实例完全构造的唯一方法是完成其构造函数 解决问题的一种方法是仅将构造函数用于实例的构造,并将(动态)初始化留给方法。在这种情况下,您可以使用以下方法:
private boolean initialized = false;
public synchronized boolean init() {
if (!initialized) {
// allocate resources, call abstract method(s)
initialized = true;
}
return initialized;
}
public synchronized void cleanup() {
if (initialized) {
// free resources, call abstract method(s)
initialized = false;
}
}
调用代码可以显式调用init()
和cleanup()
方法,或者将对init()
的调用保留为如下模式:
public void doSomething() {
if (init()) {
// go!
}
}
在init方法内部,您可以调用抽象方法,并确保正确构造完整的对象实例。@rsp建议的显式init()方法的另一种替代方法是延迟计算这些其他结果。e、 g
public int getValue() {
if (value == 0) { // some constant or value that means not-computed yet
value = blah*foo*bar;
}
return value;
}
或者,对value()的计算不会花费很多时间。总是重新计算它。30年前,你会把这些东西都藏起来。缓存会创建对象为空或过时的错误。或子类。:-)处理器现在快多了,重新计算通常更简单,有时甚至更快。查看提交的代码示例,没有迹象表明基类中使用了抽象方法。我希望这是为了简化。否则,将该方法定义为抽象方法是没有意义的 要在由子类计算的基类中缓存值,不应使用构造函数。在子类的构造函数有机会为其传递数据之前调用该方法,从而产生您观察到的效果 相反,我将为抽象方法定义一个伴随方法,该方法将检查值是否已缓存,如果未缓存,则执行缓存。 考虑这个例子:
public abstract class Base {
private final String name;
private BigInteger cachedValue;
public Base(String name) {
this.name = name;
}
public BigInteger calculate() {
final BigInteger one = BigInteger.ONE;
//do the calculation involving `value` call
return value().multiply(one);
}
protected abstract BigInteger doComplexCalculation();
protected BigInteger value () {
if (cachedValue == null) {
this.cachedValue = doComplexCalculation();
}
return this.cachedValue;
}
}
此情况下的子类示例:
public class SubClass extends Base {
private int number;
public SubClass(String name, int number) {
super(name);
this.number = number;
}
@Override
protected BigInteger doComplexCalculation() {
//do calculations and return a result which will be cached by the base class
return BigInteger.valueOf(number);
}
//The cached value can then be accessed by other methods
//through the use of protected `value` method call.
}
我认为你需要发布你的代码,我可以想出2个选择-1。不要从构造函数内部调用该方法,而要在外部显式调用。2.创建另一个将捕获附加信息的抽象方法,并在抽象方法之前调用它。顺便说一句,为什么不能更改方法的签名?我不明白为什么在构造函数中调用value(),而忽略结果。我猜是打字错误,真正的代码是这样的。value=value()???是的,没错。这就是我计划使用它的方式,请参见下面我的答案。由于计算value()几乎不是火箭科学,我将完全跳过构造函数。当他们要求getValue()时,每次只需计算它。你的意思是,我没有将抽象方法放在构造函数中,而是将它放在另一个方法中-如你所建议的初始化方法?我如何检查初始化?甚至,我该如何初始化?@Dennis,是的,这就是我的意思。假设从构造函数调用抽象方法是为了初始化实例,您可以在创建新实例后直接调用init方法,或者让初始化在对对象的第一次公共调用时完成。