0

我对以下代码有疑问(这是调用动态绑定吗?)。我对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"); }
}
4

3 回答 3

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”

于 2012-04-19T12:59:08.637 回答
0

P pq = qq;意味着pq程序的其余部分将其称为 type P。但作为创作者,你知道它真的是 type Q。所以这意味着当你调用 时pq.m(),它实际上是从类 Q 调用实现。

这称为覆盖方法。因此,当您调用 pq.m(pp) 时,您实际上是在调用: public void m(P p){System.out.println("Q::P");因为那是来自 Q 类的方法。

如果 Q 没有 am(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.

我希望这一切都有帮助。请务必阅读有关面向对象的内容。

于 2012-04-19T13:05:52.150 回答
0

动态绑定和多态性仅适用于方法调用中点左侧的对象(o.m(x)-- 仅适用于o)。参数类型在编译时静态解析。举一个更广为人知的情况:

class A { 
  public boolean equals(A other) { 
    System.out.println("A.equals called"); return true;
  }
}

A a1 = new A(), a2 = new A();
Object o = a1;
o.equals(a1); // doesn't print anything
a1.equals(o); // doesn't print anything
a1.equals(a2); // prints "A.equals called"

这里的重点是类 A 没有覆盖 Object.equals(Object),而是添加了另一个重载方法 A.equals(A)——只有当参数是声明的类型 A 时才会调用该方法。

于 2012-04-19T13:09:24.623 回答