声明的类型和创建的类型之间的关系

时间:2012-04-19 12:47:16

标签: java dynamic-binding

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

3 个答案:

答案 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) - 并且只有当参数是声明类型时才调用它甲