我正在尝试在Java中实现类似CAS的功能,但是我在类型和方法选择方面苦苦挣扎。
当我添加两个子类型时,一切都很好。当我添加具有超类型的子类型时,将发生无限递归。当再次将超型转换为精简型时,以及当我将超型添加到子类型时,再次发生相同的递归。
有人可以解释这里发生的事情以及我做错了什么吗?
public class MathMain{
public static void main(String[] args){
Constant constant = new Constant(1);
constant.add(constant);
MathObject mathObject = (MathObject)constant;
constant.add(mathObject);
constant.add((Constant)mathObject);
mathObject.add(constant);
}
}
public abstract class MathObject{
public abstract MathObject add(MathObject addend);
public abstract MathObject substract(MathObject subtrahend);
}
public class Constant extends MathObject{
public final double c;
public Constant(double c){
this.c = c;
}
public MathObject add(MathObject that){
return that.add((Constant)this);
}
public MathObject substract(MathObject that){
return that.substract((Constant)this);
}
public Constant add(Constant addend){
return new Constant(c + addend.c);
}
public Constant substract(Constant subtrahend){
return new Constant(c - subtrahend.c);
}
}
要记住的重要一点是,方法重载解析是在编译时确定的,而方法重写是在运行时确定的。
mathObject.add(constant)
选择MathObject add(MathObject addend)
方法,这是唯一add
可用的方法MathObject
。
在运行时,由于mathObject
is Constant
,MathObject add(MathObject that)
of的运行时类型Constant
已执行,因此调用that.add((Constant)this)
。由于类型that
为MathObject
,再次MathObject add(MathObject addend)
选择,这意味着您的方法正在无限递归中调用自身。
表达式Constant add(Constant addend)
将调用您的唯一方法that.add((Constant)this)
是,如果编译时间类型为that
was Constant
,因为MathObject
它没有add
接受Constant
参数的方法。
现在,对于可行的情况:
constant.add(constant)
constant.add((Constant)mathObject)
两者都Constant add(Constant addend)
直接调用,因为constant
is的编译类型,Constant
并且选择了具有更具体参数类型的方法。
我不知道这是否是一个好的解决方案,但是克服无限递归的一种方法是检查参数的类型:
public MathObject add(MathObject that){
if (that instanceof Constant)
return add((Constant) that);
else
that.add((Constant)this); // note that the casting here only makes
// sense if MathObject has an add method
// that takes a Constant. otherwise is makes
// no difference
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句