简体   繁体   中英

Java: Accessing member of a derived class when an object is declared as a base class

I have a class called ScalarObject and a class called Variable that inherits from ScalarObject. I defined "equals" on ScalarObject that always returns false, and on Variable that returns true when the strings representing them are equal.

The following code:

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

return false. The following code:

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

returns true. The following code:

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

also returns true. The problem is that I have other classes that also derive from ScalarObject. I have parts of my program objects that are declared of type ScalarObject but could be a member of any class that derives from it, so casting a ScalarObject object to a derived type won't work. For example, in one part of my program I have:

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 ");

and the program prints out "x" twice but does not print "B". The variables n1 and n2 come from the linked list "L". I suspect that the program is calling "ScalarObject.equals()" (which always returns false) and not "Variable.equals()". The problem with casting n1 and n2 to type Variable is that n1 and n2 could be instances of some other class that is also derived from ScalarObject. How do I get the program to call a member from a derived class not a base class even when it is declared as a base class?

I am using NetBeans 6.9.1 on Windows Vista.

Searching on the web has taken me to http://wiki.answers.com/Q/Can_a_base_class_access_members_of_a_derived_class which states that in Java a base class can access members of a derived class when @Override notation is used. However, when I added @Override to Variable.equals(), I got an error stating that the method does not override a method from a supertype, probably because the siguatures are different. ScalarObject.equals() takes an argument of type ScalarObject and Variable.equals() takes an argument of type Variable.

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

你想要做的是使变量的equals方法通过改变它的签名来接受ScalarObject,然后使用instanceof运算符根据传入的对象的实际类型采取不同的动作来覆盖ScalarObject.equals。

You should be very careful with the difference between overriding and overloading .

If the signatures of the equals methods in the base and the derived class match (which should be the case, see jtahlborn's answer), you have overriding. This uses dynamic binding : the correct equals method is determined at runtime, so

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

calls the equals of Variable , since the type of a1 is determined as Variable at runtime.


If the signatures of the equals methods don't match ( equals(ScalarObject so) vs equals(Variable v) ), you have overloading. This uses static binding . That is, even if you do

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

the last line will use ScalarObject.equals(ScalarObject so) , because the compiler cannot infer that a2 is of type Variable .

Long story short: always use overriding for your equals method, that is, use public boolean equals(Object o) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM