I have these 2 classes in my java program:
public class A {
private final static A five = new A(5);
public final int x;
public A(int x) {
this.x = x;
}
public boolean equals(Object o) {
return x == ((A) o).x;
}
public String toString() {
return equals(five) ? "five" : (x + "");
}
}
public class B extends A {
public final int x;
public B(int x) {
super(x);
this.x = x + 1;
}
public boolean equals(A o) {
return x == o.x;
}
public String toString() {
return "B: " + super.toString();
}
}
Now in my main i'm doing these 2 simple actions:
public static void main(String[] args) {
System.out.println(new A(5));
System.out.println(new B(5));
}
About the first line, as i expected, it will create an A object -> go to A's toString function -> get True for the equals function and finally print "five".
About the B, what i expected and what actually happening is different...
I thought it will go to B's constructor -> go to A constructor and assign the number 5 to x -> return to B constructor and assign the number 6 to B's x -> go to B's toString method and print "B: " (Until this point i was right) -> go to A's toString -> go to B's equals since the object type is B and that's what you looking at concerning method activation (* This is where i was wrong) -> return False because the x in B is 6 -> print the number 5 since we were in A's toString.
Instead, in the part where it's calling the A class toString instead of going to the B equals method it's staying in A and activate the A equals...
I have no idea why is it happening, all i know is the method activated is determined by the object type.
Hope someone could explain me what's different here... Thanks!
2 Answers 2
To expand on your answer, for future readers:
In A.toString() you call this.equals(five), where five is of type A.
In the context of A, the only equals() method matching A is A.equals(Object o). So that is the method the JVM calls.
If there were an overriding method B.equals(Object o) then this would have been called. It's not enough that there is a B.equals() method with a narrower type.
You can get the behaviour you expected by either supplying an A.equals(A a) method, or by expanding the breadth of B.equals() to take Object.
A couple of notes:
- In only a few lines you've created something pretty intricate here. I hope it's just to experiment: real code should be much more straightforward.
- If you're going to implement
equals()make it acceptObject, so you're overriding the standard method.
Comments
As the comment given explained, i didn't override the function, i overloaded the function with a whole new signature to the method.
A#equals. You've overloaded it.