Reputation: 103
At university we were given a Java program and tasked with understanding how the output comes to be the way it is. The program is the following:
interface A {
public void f(A x);
}
interface AA extends A {
public void f(B x);
}
class B implements A {
public void f (A x) {System.out.println("1");}
public void f (B x) {System.out.println("2");}
public void f (C x) {System.out.println("3");}
}
class C implements A,AA {
public void f(A x) {System.out.println("4");}
public void f(B x) {System.out.println("5");}
public void f(C x) {System.out.println("6");}
}
public class Task7 {
public static void main(String[] args) {
B b = new B(); C c = new C();
A ac = c; A ab = b;
AA aac = c;
b.f(b); c.f(c);
ac.f(b); ab.f(b);
aac.f(b); aac.f(c);
}
}
The output is "264154". I don't really understand how the last 4 numbers can be explained. can anybody help?
EDIT: To explain what is my problem a little bit further: ´b.f(b)´ obviously will print out 2 because you are giving a B reference to a B object, and ´c.f(c)´ will print 6 for the same reason.
´ab.f(b)´ will call ´b.f(b)´ because its dynamic type is B. Now, I don't understand why the argument ´b´, which before has been seen by the same class as a ´B´, is now understood as an ´A´, so that "1" gets printed instead of "2". And the same goes for the other method calls, I just don't understand why the same argument with the same underlying object is interpreted differently
Upvotes: 3
Views: 77
Reputation: 688
First of all you have to really understand polymorphism.
I'm not going to explain why the first two values are printed out, but I consider interesting knowing why the other ones have those outputs.
So, let's check the third one: ac.f(b);
ac is an instance of A: A ac = c;
and c is an instance of C: C c = new C();
. Therefore, A ac = new C();
which means that ac can only use functions inside C class and among those functions it can only call the ones written inside A interface: public void f(A x) {System.out.println("4");}
(The compiler doesn't care about the type of object in the parameters section)
Other example: ab.f(b);
that's the fourth number you're getting in the output. ab is an instance of A: A ab = b
and b is an instance of B: B b = new B();
. Thus, A ab = new B();
. Which implies that ab can call all functions declared inside B and inside A that's why: public void f (A x) {System.out.println("1");}
.(Remember they must be declared in both sections, not just in one).
Upvotes: 1
Reputation: 533530
Polymorphism applied to the object on the left of the .
only. The compiler determines which method signature to call at compile time, regardless of the value passed.
e.g.
B b = new B();
b.f((A) null);
b.f((B) null);
b.f((C) null);
prints 123
as only the type of the reference known at compile time matters.
Similarly, when invoking a static method, only the type of reference matters if you use a reference.
Thread t = null;
t.yield(); // call Thread.yield() so no NullPointerException.
I just don't understand why the same argument with the same underlying object is interpreted differently
The method signature is determined at compile time based on the reference type.
Another way of looking at it is that polymorphism only applied for overridden methods, not overloaded methods.
Upvotes: 3