I have an question about the following code (Is this call dynamic binding?). I feel confused about 3 point.
First, what is the mean of the variable pq? Does pd still be the data type of P or be the Q?
Second, when I invoke the pq.m(pp) method, why the result become Q::P but not P::Q?
Finally, what is this mean ((P) qq).m(qq);? I hope somebody could solve my problem.
The result of the following code will be
P::Q, Q::P, Q::Q, R::P, Q::P, Q::Q, Q::Q
class Test {
public static void main(String[] args) {
P pp = new P();
Q qq = new Q();
R rr = new R();
P pq = qq;
pp.m(qq);
pq.m(pp);
pq.m(qq);
rr.m(pp);
qq.m(pq);
qq.m(qq);
((P) qq).m(qq);
}
}
class P {
public void m(P p){System.out.println("P::P"); }
public void m(Q p){System.out.println("P::Q"); }
public void m(R c){System.out.println("P::R"); }
}
class Q extends P {
public void m(P p){System.out.println("Q::P"); }
public void m(Q p){System.out.println("Q::Q"); }
public void m(R c){System.out.println("Q::R"); }
}
class R extends Q {
public void m(P p){System.out.println("R::P"); }
public void m(Q p){System.out.println("R::Q"); }
public void m(R c){System.out.println("R::R"); }
}
P pq = qq;
means that pq
is known to the rest of the program as a type P
. But as the creator, you know it's really of type Q
. So this means that when you call pq.m()
, it's really calling the implementation from class Q.
It's called overriding a method. So when you call pq.m(pp), you are really calling:
public void m(P p){System.out.println("Q::P");
because that is the method from class Q.
If Q did not have a m(P) method, then it would automatically call the superclass method, the one from P.
((P) qq).m(qq);
is the same as doing:
P pqq = (P)qq; // pqq is known as P type, but it's instance is still the original Q type
pqq.m(qq); // Again, since pqq is truly an instance of Q, it calls Q.m(Q)
You should really read about inheritance. This is a bigger subject than can be explained here.
All this being said, your example doesn't illustrate its power well. But for example, if class Q had an extra method, public void sayHello();
, then
Q q = new Q();
P p = new Q();
q.sayHello(); // This would be legal
p.sayHello(); // This would be illegal because the compiler knows p as a declared instance of P, even though you know it's truly a Q.
((Q)p).sayHello(); // This would be legal because you told the compiler to look at p as an instance of Q. It's called a cast.
I hope this all helps. Be sure to go read up on object orientation.