2012-04-19 83 views
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"); } 
} 
+3

没有变量'pd',所以很难回答你的第一个问题... – 2012-04-19 12:51:00

+1

但要回答所有的问题问题,你应该阅读[Java中的继承](http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html)。 – 2012-04-19 12:52:44

+0

其中pd ...? – 2012-04-19 12:53:03

回答

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没有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. 

我希望这一切帮助。请务必阅读面向对象。

0

开始,我想你的意思是pq,而不是pd。由于Q延伸P,所以Q也是P型。这就像说苹果是一种水果。所以你拿苹果(Q)说:这是一个水果(P)。当调用pq方法,他们将调用来自Q类的方法,因为pq仍然问答对象。 在最后一部分,当你做((P) qq).m(qq);,相同执行以下操作:

P p = (P) qq; 
q.m(qq); 

所以如上所说,代码仍然会调用该方法从Q类,印刷“Q :: Q”

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(对象),而只是增加了一个重载的方法A.等于(A) - 只有当参数是声明的类型A时才被调用。

+0

对不起...我不低调。我发现你的解释很混乱,因为我认为它听起来像你描述的是C++而不是java。您添加的最后一段改进了您的答案。 – stevevls 2012-04-19 13:13:08