我正在尝试在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);
}
}
答案 0 :(得分:2)
要记住的重要一点是,方法重载是在编译时确定的,而方法重写是在运行时确定的。
mathObject.add(constant)
选择MathObject add(MathObject addend)
方法,这是add
唯一可用的MathObject
方法。
在运行时,由于mathObject
的运行时类型为Constant
,MathObject add(MathObject that)
的{{1}}被执行,并且它调用Constant
。由于that.add((Constant)this)
的类型为that
,因此再次选择MathObject
,这意味着您的方法在无限递归中调用自身。
MathObject add(MathObject addend)
表达式调用Constant add(Constant addend)
的唯一方法是that.add((Constant)this)
的编译时类型是that
,因为Constant
没有' t有MathObject
方法接受add
参数。
现在,对于有效的案例:
Constant
直接调用constant.add(constant)
constant.add((Constant)mathObject)
,因为Constant add(Constant addend)
的编译类型是constant
,并且选择了具有更具体参数类型的方法。
我不知道这是否是一个很好的解决方案,但是克服无限递归的一种方法是检查参数的类型:
Constant