I'm pretty sure I can't be the first one to stumble over this but I can't find an answer. This is homework.
class Tier{}
class Fisch extends Tier{}
class Vogel extends Tier{}
class Huhn extends Vogel{}
class Spatz extends Vogel{}
class Karpfen extends Fisch{}
class Super{
public void m(Tier t1, Tier t2){
System.out.println("1");
}
public void m(Tier t, Fisch f){
System.out.println("2");
}
public void m(Fisch f, Tier t){
System.out.println("5");
}
}
class Sub extends Super{
public void m(Tier t1, Fisch t2){
System.out.println("3");
}
public void m(Vogel v, Fisch f){
System.out.println("4");
}
}
public class TierTest{
public static void main(String[] args) {
Tier t1 = new Tier();
Tier t2 = new Vogel();
Fisch f = new Karpfen();
Vogel v1 = new Vogel();
Vogel v2 = new Spatz();
Huhn h = new Huhn();
Karpfen k = new Karpfen();
Super sup1 = new Super();
Super sup2 = new Sub();
sup1.m(h, v2);
sup2.m(v1, k); //4 expected, got 3
sup1.m(t1, t2);
sup1.m(v1, k);
sup1.m(v2, f);
sup2.m(v1, f); //4 expected, got 3
}
}
Both times a Vogel(bird) (declaration and runtime type) and some kind of fish. Why is m(Tier, Fisch) chosen over m(Vogel, Fisch) ?
The fist parameter would be a perfect match. The rest of this fits my intuition.
Sorry if I'm just too numb to find a similar question.
Have a nice weekend, Stephan
Here :
Vogel v1 = new Vogel();
Karpfen k = new Karpfen();
...
Super sup2 = new Sub();
...
sup2.m(v1, k); //4 expected, got 3
sup2
is declared with the Super
class type.
The method chosen by the compiler relies on the class of the declared variable, not on the runtime instance.
So, the compilers looks for a method that matches in the Super
class.
In Super
class, these are the m()
potential method candidates :
public void m(Tier t1, Tier t2){
System.out.println("1");
}
public void m(Tier t, Fisch f){
System.out.println("2");
}
public void m(Fisch f, Tier t){
System.out.println("5");
}
The compiler chooses the most specific method among other to match with v1
and k
arguments declared types :
This method is selected :
public void m(Tier t, Fisch f){
System.out.println("2");
}
Now, at runtime, the method is invoked on the runtime object (polymorphism principle).
As the runtime class that the sup2
variable refers to is Sub
, the overloaded method of Sub
is invoked :
public void m(Tier t1, Fisch t2){
System.out.println("3");
}
And for this second invocation :
sup2.m(v1, f); //4 expected, got 3
It is exactly the same reasoning.