2012-04-10 14 views
2

Angesichts der folgenden Java-Code:Verständnis Java Vererbung

class mainul { 

    public static void main(String[] args) { 

    /*block 1*/ 
     B b1 = new B(); 
     A a1 = b1; 
     a1.m1(b1); 

    /*block 2*/ 
     B b2 = new B(); 
     B a2 = b2; 
     b2.m1(a2); 
    } 
} 

class A { 

    public static void p(Object o) { 
     System.out.println(o.toString()); 
    } 

    public void m1(A a) { 
     p("m1(A) in A"); 

    } 
} 

class B extends A { 

    public void m1(B b) { 
     p("m1(B) in B"); 
    } 
} 

jemand etwas Licht auf, warum die Ausgabe dieses Programms vergießen ist

m1(A) in A 
m1(B) in B 

Man würde erwarten, dass der Ausgang von Block 1 zu sein " m1 (B) in B "aufgrund der Tatsache, dass der dynamische Typ von a1 B ist. Ich habe bemerkt, dass die Funktionssignaturen in A und B für m1 nicht übereinstimmen (man erwartet ein Objekt vom Typ A und das andere von B als Argument) und die Methode in A scheint Priorität zu bekommen, kann sie aber nicht wirklich mit meiner Ausgabe verknüpfen, da sie nicht mit dieser übereinstimmt Der Ausgang von Block2.

Vielen Dank für Ihre Zeit

Antwort

7

Wie Sie bemerkt haben, B.m1(B) nicht A.m1(A) außer Kraft setzen, da sie unterschiedliche Argumente (versuchen Sie die @Override Anmerkung hinzugefügt und Sie werden der Compiler beschweren sehen). So kann es nie über einen Verweis auf eine A aufgerufen werden.

Es kann jedoch über eine Referenz auf eine B aufgerufen werden.

+0

in der Tat, lassen Sie es eine A-Instanz erwarten, und es wird funktionieren. – MarioDS

0

Die beiden Methodensignaturen sind unterschiedlich, wie Oli sagte.

Wenn Sie jeder von ihnen nennen hier:

B b1 = new B(); 
    A a1 = b1; 
    a1.m1(b1); 

    /*block 2*/ 
    B b2 = new B(); 
    B a2 = b2; 
    b2.m1(a2); 

Sie zuerst ein Objekt vom Typ A übergeben, dann ein Objekt vom Typ B. passieren, dass alle Java betrifft in diesem Zusammenhang es nicht kümmere dich darum, was du aus dem Objekt gemacht hast, was es ist.

+0

Haben Sie übrigens auch eine 'toString'-Methode für jedes Objekt definiert und übergeben Sie das Objekt dann an Ihre' p (Object o) '-Methode –

1

Die aufgerufene Methode wird zur Kompilierzeit gesetzt (in diesem Fall A.m1 (A)). Ich weiß, dass du denkst, dass es dynamisch ist, oder? Dynamische Bindung ist Laufzeitbindung. Nun ja, ist es, aber es ist nur für die Methode auf A.m1 (A) dynamisch. Daher kann jede Unterklasse von A eine alternative Implementierung bereitstellen, aber ihre Signatur muss identisch sein, andernfalls ist dies eine überladene Methode, die nicht dieselbe Methode ist.

Dies bedeutet auch, dass die in einem Aufruf verwendeten Parameter für die dynamische Bindung nicht berücksichtigt werden. Der Methodenname und die formale Signatur werden zur Kompilierzeit festgelegt. Ändern Sie die Typen und es ist nicht die gleiche Methode und wird nicht aufgerufen.

Sie können dies tun, den Compiler zu zwingen, um die Methode zu sehen:

a1.m1((A)b1) 

, dass der Compiler sagt, welche Methode Sie anrufen möchten.

1

folgen einfach den Code:

Block 1

B b1 = new B(); //- variable b1 (type is B) points to instance of B() 

A a1 = b1;  //- variable a1 (type is A) points to instance of B() .. same as b1 is 
        // pointing to. 

a1.m1(b1);  // Call Method m1 on a1 (i.e. of class A) ..IMP catch > as a1 holds 
        // object of b1, if there is method in Class A which is overriden in B, 
        // call that overriden method. But here method m1() is not overriden 
        // by B it will call method of class A. 

Block 2

B b2 = new B(); // variable b2 (type B) points to instance of B() 

B a2 = b2;  // variable a2 (type B) points to same instance as b2 is pointing to. 

b2.m1(a2);  // call method m1 of b2 (of class B). There is only one method m1 in b2 
       // and b2 holds object of B, it must call method of class B 

Wenn Sie möchten, dass Block 1 nicht "m1 (B) in B" ist, markieren Sie einfach die Methode in Klasse A als virtuell und überschreiben Sie sie in Klasse B.