2017-05-20 2 views
1

Ich bin Java studiert, und ich wurde den folgenden Code angegeben:Java-Unterklassen: Was ist die Methode, die ausgelöst wird?

public class A { 
    public void m(A a) { System.out.println("A.m:A"); } 
    public void m(B b) { System.out.println("A.m:B"); } 
} 

public class B extends A { 
    private void m(C c) { System.out.println("B.m:C"); } 
    public void m(B b) { System.out.println("B.m:B"); } 
} 

public class C extends A { 
    public static void main(String args[]) { 
     A ab = new B(); 
     B bb = new B(); 
     A ac = new C(); 

     ab.m(ac); // My answer: A.m : A || correct 
     ab.m(ab); // My answer: B.m : B || Correct answer: A.m : A 
     ab.m(bb); // My answer: B.m : B || correct 
     bb.m(ac); // My answer: compile error || Correct answer: A.m : A 
     bb.m(ab); // My answer: B.m : B || Correct answer: A.m : A 
     bb.m(bb); // My answer: B.m : B || correct 
     ac.m((A)bb); // My answer: A.m : A || correct 
     bb.m((B)ac); // My answer: compile error || Correct answer: run-time error [Class cast exception] --> I UNDERSTAND THIS 
     bb.m((B)ab); // My answer: B.m : B || correct 
    } 
} 

ich schreiben musste, was das Ergebnis der Anrufe in Hauptfunktion sein würde. Wie Sie sehen können, habe ich die meisten Antworten falsch verstanden. Was ich versuche zu verstehen, ist, wie kann ich feststellen, welche Klasse Funktion aufgerufen wird, wenn ich eine Variable der Art der Superklasse, die mit dem Konstruktor einer Unterklasse erstellt wurde?

+1

Mögliches Duplikat von [Java dynamische Bindung und Methode überschreiben] (http://stackoverflow.com/questions/321864/java-dynamic-binding-and-method-overriding) – Seelenvirtuose

Antwort

0

Um Fragen dieser Art zu beantworten, müssen Sie drei Dinge zu beachten:

  1. Was ist die Laufzeittyp des Objekts, auf dem Sie die Methode aufrufen?
  2. Was ist der Kompilierungszeittyp des Arguments der Methode?
  3. Würden Fehler bei der Konvertierung von Argumenten auftreten?

zu beantworten (1) auf der rechten Seite der Erklärung aussehen: ab und bb sind vom Typ B, während ac vom Typ C.

zu beantworten (2) Blick auf die linke Seite der Deklaration: ab ein A ist, bb ein B ist, und ac ist ein A.

Um (3) zu antworten, nach Abgüssen suchen und mit dem Typ aus Teil (1) vergleichen. Das Konvertieren einer Unterklasse in eine Basisklasse ist erlaubt, wie in (A)bb. Die Konvertierung zwischen Geschwistern, wie in (B)ac, führt jedoch zu Kompilierungsfehlern, wenn Sie beim Kompilieren-Typ feststellen können, dass Sie ein Geschwister konvertieren, oder Laufzeitfehler, wenn der Kompilierungstyp von einem übergeordneten Element stammt.

Sobald Sie Antworten auf (1) und (2) haben und die durch (3) verursachten Fehler behoben haben, müssen Sie den Quellcode ansehen und die Methodenüberladung der Klasse (1) auswählen, die dem Typ entspricht der Klasse von (2).

+0

Vielen Dank! Sehr detailliert und gut erklärt :) – tropicaldc

0

Die obige Antwort macht vollkommen Sinn, also werde ich nicht wiederholen, was dieser Benutzer bereits gesagt hat. Die Szenarien, in denen Ihre Antworten falsch sind (anders als die, die Sie bereits erwähnt haben), beziehen sich alle auf die Übergabe eines Superklassenobjekts, das mit einer Unterklassenimplementierung als Argument erstellt wurde, an die Methode m.

A ab = new B(); 
B bb = new B(); 
A ac = new C(); 

ab.m(ab); // My answer: B.m : B || Correct answer: A.m : A 
bb.m(ac); // My answer: compile error || Correct answer: A.m : A 
bb.m(ab); // My answer: B.m : B || Correct answer: A.m : A 

In all diesen Aussagen darüber, Sie übergeben tatsächlich ein Objekt von A obwohl die Umsetzung der Unterklasse ist. Sie können also ohne weitere Verwirrung nach der Methode suchen, die den Parameter des Objekts A übernimmt. Weil die tatsächliche Objektimplementierung nur zur Laufzeit aufgelöst werden kann.

Verwandte Themen