我对以下代码有疑问(这是调用动态绑定吗?)。我对3点感到困惑。
首先,变量pq的平均值是多少? pd仍然是P的数据类型还是Q?
其次,当我调用pq.m(pp)方法时,为什么结果变为Q :: P而不是P :: Q?
最后,这是什么意思((P)qq).m(qq);?我希望有人能解决我的问题。
以下代码的结果将是
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"); }
}
答案 0 :(得分:0)
开始,我认为你的意思是pq
,而不是pd
。由于Q延伸P,Q也是P型。这就像是说苹果是水果。所以你拿苹果(Q)说:它是一种水果(P)。当您调用pq
方法时,它们将从Q类调用方法,因为pq
仍然是Q对象。
在最后一部分中,当您执行((P) qq).m(qq);
时,与执行以下操作相同:
P p = (P) qq;
q.m(qq);
如上所述,代码仍将从Q类调用该方法,打印" Q :: Q"
答案 1 :(得分:0)
P pq = qq;
表示pq
已被程序的其余部分称为类型P
。但作为创作者,你知道它实际上是Q
类型。所以这意味着当你调用pq.m()
时,它实际上是从Q类调用实现。
它被称为覆盖方法。所以当你打电话给pq.m(pp)时,你真的在打电话:
public void m(P p){System.out.println("Q::P");
因为这是Q类的方法。
如果Q没有m(P)方法,那么它会自动调用超类方法,即P中的方法。
((P) qq).m(qq);
与执行相同:
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)
你应该真正阅读有关继承的内容。这是一个比这里可以解释的更大的主题。
所有这些都说,你的例子并没有很好地说明它的力量。但是,例如,如果Q类有一个额外的方法public void sayHello();
,那么
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.
我希望这一切都有帮助。请务必阅读面向对象。
答案 2 :(得分:0)
动态绑定,因此多态,仅适用于方法调用中{+ 1}}的点左侧的对象 - 仅适用于o.m(x)
)。参数类型在编译时静态解析。采取一个更为人熟知的情况:
o
这里的重点是A类不会覆盖Object.equals(Object),而是只添加另一个重载方法A.equals(A) - 并且只有当参数是声明类型时才调用它甲