Skip to content
Advertisement

java polymorphism aliasing issue

If there’s 3 classes. A, B and C. class B extends A and class C extends B.

class A has equals method:

JavaScript

class B has equals method:

JavaScript

and class C has euals method:

JavaScript

And the main has these code lines:

JavaScript

I can’t understand why the equals method of class A is being executed.

I know that overloaded methods are bonded using static binding. But a points to the “C part of the object” after aliasing and there’s the method equals of class C. Why isn’t it the equals method of class C that will execute?

Advertisement

Answer

A method in a subclass overrides a method in the superclass only if the parameters have the same types.

The Object class defines an equals() method:

JavaScript

When you define class A, it inherits the equals routine from Object. You define a new equals, but the parameter type is different, so it doesn’t override the one in Object; instead, it becomes an overload. The result is that A has two overloaded equals methods:

JavaScript

Similarly, the equals in B won’t override either equals, so the result is three overloaded equals methods:

JavaScript

In class C, the new equals method does override the one in Object, so there are still three equals methods:

JavaScript

Now, here’s your code:

JavaScript

When you say a.equals(c), the compiler sees that a has type A. Therefore it looks at the methods in A to see which one to execute. (The compiler doesn’t know that a will have type C at run time; therefore, it won’t look at the methods in C.)

There are two methods to choose from, as shown above:

JavaScript

Both of them could be used on the parameter c, since c is an Object and it is an A. In that case, when one parameter is a subclass of the other, the compiler chooses the “closest” one, in essence. C is only two subclasses away from A, and it’s three subclasses away from Object, so it chooses the overload with parameter A, which is the one you defined in A. And note that this equals method was never overridden. So it executes the code that you wrote in class A.

But suppose you had written:

JavaScript

By casting c to an Object, you’re forcing the compiler to look at it as an Object. Now when it chooses between the overloads, it must choose the one with the Object parameter, because an Object cannot automatically be converted to an A (because not every Object is an A). Thus, it would choose the inherited method. And since, at run time, the object actually is of class C, and since class C has an equals method that overrides the one in Object, in this case it would execute the code written in class C.

Your code is a nice example for demonstrating how overloading and overriding work. In real life, however, it’s a bad idea to write an equals() method whose parameter is anything other than Object, because it won’t override and it could lead to confusion. Also, it’s a good practice to put @Override on any method that you think will override a method in a superclass. That way, if you goof and use the wrong parameters, the compiler will catch it before you get a run-time bug that could be very difficult to track down.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement