继承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()接受变量类型的参数
# 1 楼答案
equals方法必须在所有类中定义为
public Object equals(Object obj)
,以便正确重写(提示,请注意@Override
注释编译错误)# 2 楼答案
这里要做的是使变量的equals方法覆盖ScalarObject。通过更改其签名以接受ScalarObject,然后使用instanceof运算符根据传入对象的实际类型采取不同的操作,等于
# 3 楼答案
您应该非常小心重写和重载之间的区别
如果基类和派生类中的
equals
方法的签名匹配(应该是这种情况,请参见jtahlborn的答案),那么您就有了覆盖。这使用了动态绑定:正确的equals方法是在运行时确定的,因此调用
Variable
的等号,因为a1
的类型在运行时被确定为Variable
如果
equals
方法的签名不匹配(equals(ScalarObject so)
与equals(Variable v)
),则存在重载。这将使用静态绑定。也就是说,即使你这样做了最后一行将使用
ScalarObject.equals(ScalarObject so)
,因为编译器无法推断a2
属于Variable
类型长话短说:始终对equals方法使用重写,即使用
public boolean equals(Object o)