有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

继承Java:当对象被声明为基类时,访问派生类的成员

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

以下代码:

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强制转换为类型变量的问题在于,n1和n2可能是另一个类的实例,该类也派生自ScalarObject。我如何让程序调用派生类而不是基类的成员,即使它被声明为基类

我正在Windows Vista上使用NetBeans 6.9.1

在web上搜索将我带到了http://wiki.answers.com/Q/Can_a_base_class_access_members_of_a_derived_class,它指出在Java中,当使用@Override表示法时,基类可以访问派生类的成员。然而,当我向变量添加@Override时。equals(),我得到一个错误,指出该方法不重写超类型中的方法,可能是因为siguature不同。ScalarObject。equals()接受ScalarObject和Variable类型的参数。equals()接受变量类型的参数


共 (3) 个答案

  1. # 1 楼答案

    equals方法必须在所有类中定义为public Object equals(Object obj),以便正确重写(提示,请注意@Override注释编译错误)

  2. # 2 楼答案

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

  3. # 3 楼答案

    您应该非常小心重写重载之间的区别

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

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

    调用Variable的等号,因为a1的类型在运行时被确定为Variable


    如果equals方法的签名不匹配(equals(ScalarObject so)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)