1

我有一个名为 ScalarObject 的类和一个继承自 ScalarObject 的名为 Variable 的类。我在 ScalarObject 上定义了“equals”,它总是返回 false,并且在表示它们的字符串相等时返回 true 的 Variable。

以下代码:

ScalarObject a1 = new Variable("a");
ScalarObject a2 = new Variable("a");
System.out.println(a1.equals(a2));

返回假。以下代码:

Variable a1 = new Variable("a");
Variable a2 = new Variable("a");
System.out.println(a1.equals(a2));

返回真。以下代码:

ScalarObject a1 = new Variable("a");
ScalarObject a2 = new Variable("a");
System.out.println(((Variable) a1).equals(((Variable) a2)));

也返回真。问题是我还有其他类也派生自 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 转换为变量类型的问题在于,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() 时,我收到一条错误消息,指出该方法不会覆盖超类型中的方法,可能是因为符号不同。ScalarObject.equals() 接受一个 ScalarObject 类型的参数,而 Variable.equals() 接受一个变量类型的参数。

4

3 回答 3

4

equals 方法必须在所有类中定义public Object equals(Object obj),以便它们正确覆盖(提示,听@Override注释编译错误)。

于 2013-06-04T19:30:40.000 回答
0

您在这里要做的是使变量的 equals 方法覆盖 ScalarObject.equals,方法是更改​​其签名以接受 ScalarObject,然后使用 instanceof 运算符根据传入对象的实际类型采取不同的操作。

于 2013-06-04T19:31:56.630 回答
0

您应该非常小心覆盖重载之间的区别。

如果基类和派生类中方法的签名equals匹配(应该是这种情况,请参阅 jtahlborn 的答案),那么您就有了覆盖。这使用动态绑定:正确的 equals 方法是在运行时确定的,所以

ScalarObject a1 = new Variable("a");
a1.equals(...);

调用 equals of 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).

于 2013-06-04T19:43:39.607 回答