Reputation: 477
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?
Upvotes: 2
Views: 202
Reputation: 173
Let's analyze one by one.
f2 = new Son(3,10);
As per concept Son object will be the binded at run time.
Then you called
f2.m(s1)
Now when it searches for m method in the Son object. It found that there are two of them 1. m(Father f) and 2. m(Son s).
But reference f2 was of type Father and only m(Father f) is common between Son and Father object hence m(Father f) of Son object will be selected at runt time for execution (in short m(Son s) will not be visible with Father as reference). That's why you are seeing that result.
You can debug the code too. It will show you the same execution flow.
Upvotes: 1
Reputation: 8598
f2
is a reference of type Father
. Even though the object it references is a Son
, the compiler still only allows using any methods that exist in Father
when accessing a reference of that type. Therefore there is no other choice but using the method with signature int m(Father)
(as it's the only one that exists in Father
). Since Son
has an override for this method, that override is executed.
f2.m(s1) searches dynamically for a Son.m(Son) method
That's where your error is rooted. It's not looking for a Son.m(Son)
method, it's looking for a Father.m(Son)
method and finds a Father.m(Father)
method. Calling the override happens at a later point.
Upvotes: 2
Reputation: 639
f2 is declared as Father then instantiate by Son. The thing is in Father class the only m method is the one that accepts Father as input parameter. So when you instantiate f2 by Son class only the int m(Father f)
is available for overriding. (as long as f2 is concern, there is not a int m(Son f)
method) that's why f2.m(s1) returns 100.
Upvotes: 2