我有一个名为ScalarObject的类和一个名为Variable的类,它继承自ScalarObject。我在ScalarObject上定义了“equals”,它总是返回false,而在Variable上,当表示它们的字符串相等时返回true。
以下代码:
ScalarObject a1 = new Variable("a");
ScalarObject a2 = new Variable("a");
System.out.println(a1.equals(a2));
返回false。以下代码:
Variable a1 = new Variable("a");
Variable a2 = new Variable("a");
System.out.println(a1.equals(a2));
返回true。以下代码:
ScalarObject a1 = new Variable("a");
ScalarObject a2 = new Variable("a");
System.out.println(((Variable) a1).equals(((Variable) a2)));
也会返回true。问题是我有其他类也派生自ScalarObject。我的部分程序对象声明为ScalarObject类型,但可以是从中派生的任何类的成员,因此将ScalarObject对象转换为派生类型将不起作用。例如,在我的程序的一部分中,我有:
protected void neighbor_simplify(LinkedList<ScalarObject> L, char op) {
...
if(n1 instanceof Variable && n2 instanceof Variable) {
System.out.println(((Variable) n1).getSymbol());
System.out.println(((Variable) n2).getSymbol());
}
if(n1.equals(n2)) { // x+x=2*x
System.out.println("B ");
并且程序打印出“x”两次,但不打印“B”。变量n1和n2来自链表“L”。我怀疑该程序正在调用“ScalarObject.equals()”(它总是返回false)而不是“Variable.equals()”。将n1和n2转换为Variable类型的问题是n1和n2可能是某些其他类的实例,这些类也是从ScalarObject派生的。如何将程序从派生类调用成员而不是基类,即使它被声明为基类也是如此?
我在Windows Vista上使用NetBeans 6.9.1。
在网上搜索已经转到http://wiki.answers.com/Q/Can_a_base_class_access_members_of_a_derived_class,它指出在Java中,当使用@Override表示法时,基类可以访问派生类的成员。但是,当我将@Override添加到Variable.equals()时,我收到一条错误,指出该方法没有覆盖超类型的方法,可能是因为siguatures不同。 ScalarObject.equals()接受ScalarObject类型的参数,Variable.equals()接受Variable类型的参数。
答案 0 :(得分:4)
equals方法必须在所有类中定义为public Object equals(Object obj)
,以便它们正确覆盖(提示,监听@Override
注释编译错误)。
答案 1 :(得分:0)
你要做的是让变量的equals方法通过改变它的签名来覆盖ScalarObject,然后使用instanceof运算符根据传入对象的实际类型采取不同的动作。覆盖ScalarObject.equals。
答案 2 :(得分:0)
您应该非常小心覆盖和重载之间的区别。
如果基类和派生类中的equals
方法的签名匹配(应该是这种情况,请参阅jtahlborn的答案),那么你已经超越了。这使用动态绑定:在运行时确定正确的equals方法,所以
ScalarObject a1 = new Variable("a");
a1.equals(...);
调用Variable
的等于,因为a1
的类型在运行时被确定为Variable
。
如果equals
方法的签名不匹配(equals(ScalarObject so)
vs equals(Variable v)
),则表示您已超载。这使用静态绑定。也就是说,即使你做了
Variable a1 = new Variable("a");
ScalarObject a2 = new Variable("a");
a1.equals(a2);
最后一行将使用ScalarObject.equals(ScalarObject so)
,因为编译器无法推断a2
的类型为Variable
。
长话短说:总是使用覆盖你的equals方法,即使用public boolean equals(Object o)
。