下面是从5个类中选择的代码。
每个类必须有一个equals()方法,该方法可以将其类的对象与5个类中的任何一个或所有类的对象进行比较。
我的策略是为了精度将每个对象值转换为double类型。
每个类都继承Number,每个类都有一个doubleValue()方法可以利用。
代码将无法编译,除非我在执行doubleValue()之前将x类型转换为RationalN
但是在执行代码时,当比较另一个类的对象时,它会报错,因为它不能被类型转换为那个类。
我从这里往哪里走?
public class RationalN extends Number{
private int numerator;
private int denominator;
public RationalN(int x, int y){
if (y == 0){
throw new ArithmeticException("cannot devide by zero");
} else {
this.numerator=x;
this.denominator=y;
}
}
public double doubleValue(){
double value = (double)numerator/(double)denominator;
return (double)value;
}
public boolean equals(Object x){
if (((RationalN)x).doubleValue() == this.doubleValue()){
return true;
} else {
return false;
}
}
从我从你的帖子中得到的,你想检查等于是否由你的对象表示的数值等于参数对象的数值。因此,比较类的方法是而不是。相反,你的equals()方法应该看起来像这样:
public boolean equals(Object x) {
if(this == x)
return true;
if(x == null)
return false;
if(!(x instanceof Number))
return false;
Number n = (Number)x;
return (n.doubleValue() == this.doubleValue());
}
然而,这违反了equals()契约:new RationalN(1,1).equals(new Integer(1))将返回true,但是new Integer(1)。= (new RationalN(1,1));不会——上面的equals()方法违反了对称性。因此,引入一个实现Number的抽象类(比如MyNumber)是合适的,该抽象类仅由您的五个类扩展,并以上述方式(使用instanceof MyNumber)实现equals()。
edit:我刚刚意识到number有doubleValue()
作为number类中的抽象方法。好的,这很完美。像这样在所有五个类中实现等号。或者,如果Number不需要作为抽象类,那么请阅读下面的内容,以了解您可以创建自己的抽象类来实现equals()
并保存重复的代码。
public boolean equals(Object x)
{
if(x instanceof Number == false)
return false;
Number other = (Number) x;
return other.doubleValue() == doubleValue();
}
你不能做你在等号中所做的事情的原因是因为你正在将你试图比较的任何东西强制转换为一个RationalN类。当对非RationalN类执行此操作时,将导致ClassCastException。
因为所有的类都扩展Number,并且doubleValue()
被声明为Number可用的方法,你现在可以将这些类强制转换为Number(如果它们是Number的实例),然后从那里访问方法。
我希望这有意义。我鼓励您仔细阅读接口和多态性。
edit:顺便说一句,如果您不需要扩展Number,您可以创建一个具有抽象方法doubleValue()
的抽象类,然后您可以在抽象类中提供equals的具体实现(我上面提供的)。然后让所有五个类都扩展抽象类。然后,它们将各自实现自己版本的doubleValue()
,但将共享在抽象类中定义的equals()
,从而消除将equals()
复制/粘贴到所有五个类中的情况。如果您不需要扩展Number,这将是理想的路由。