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

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 に答える
0

pq始めて、あなたはではなくを意味していると思いますpd。Q は P を拡張するため、Q も P タイプです。リンゴは果物だと言っているようなものです。それで、あなたはリンゴ (Q) を取り、こう言います: それは果物です (P)。pqメソッドを呼び出すと、Q オブジェクトのままであるため、Q クラスからメソッドが呼び出されますpq。最後の部分で、 を行う((P) qq).m(qq);場合は、次のことを行うのと同じです。

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

上記のように、コードは引き続き Q クラスからメソッドを呼び出し、"Q::Q" を出力します。

于 2012-04-19T12:59:08.637 に答える