I have a question about how this program selects the method.
Code(constructors aside):
class Father {
int x;
..
public int m(Father f) {
return (f.x - this.x);
}
}
class Son extends Father {
int y;
...
public int m(Father f) {
return 100;
}
public int m(Son s) {
return super.m(s) + (s.y - this.y);
}
}
Main:
Father f1, f2;
Son s1;
f1 = new Father(3);
f2 = new Son(3,10);
s1 = new Son(4,21);
System.out.println(f1.m(s1) + f2.m(s1));
I don't understand why f2.m(s1)
prints 100.
Personally I understood that if there are 2 methods with the same name, if there is an overload the choice is made with static types, and if override it's made with dynamic types;
f1.m(s1)
searches dynamically a Father.m(Son)
method, but it doesn't exist and Father.m(Father)
is chosen instead
f2.m(s1)
searches dynamically for a Son.m(Son)
method, which exists and is an overload, so i think it should now prioritize static types and that searches for a Father.m(Son)
method, which doesn't exist but the closest one is the Father.m(Father)
.
Instead, the Son.m(Father)
method is chosen: it is the method that is overloaded by the Son.m(Son) method okay, but it doesn't come out from the static search, so why it is chosen?
f2
is a reference of typeFather
. Even though the object it references is aSon
, the compiler still only allows using any methods that exist inFather
when accessing a reference of that type. Therefore there is no other choice but using the method with signatureint m(Father)
(as it's the only one that exists inFather
). SinceSon
has an override for this method, that override is executed.That's where your error is rooted. It's not looking for a
Son.m(Son)
method, it's looking for aFather.m(Son)
method and finds aFather.m(Father)
method. Calling the override happens at a later point.