2015-06-07 9 views
5

Kann mir jemand das Ergebnis dieser Ausführung erklären? Ich kann nicht merken, warum jede Methode aufgerufen wird. Und wie unterscheiden wir den realen Typ vom scheinbaren Typ? Danke :)Vererbung in Java, scheinbarer Typ vs. tatsächlicher Typ

public class JavaApplication15 { 
    public static void main(String[] args) { 
     A a = new A(); 
     B b= new B(); 
     A ab = new B(); 
     b.f(a); 
     b.f(b); 
     b.f(ab); 
    } 
} 

public class A { 
    private final String id="A"; 
    public void f(A x){ 
    System.out.println("Send a fax to "+ x) ; 
    } 
    public String toString(){return id;} 
} 

public class B extends A{ 
    private final String id="B"; 
    public void f(B x){ 
    System.out.println("Send an email to"+ x) ; 
    } 
    public String toString(){return id;} 
} 

Ergebnis:

Send a fax to A 
Send an email to B 
Send a fax to B 

Antwort

3

Sie sind overloading, die (pro die wikipedia)mehrere Methoden mit dem gleichen Namen mit unterschiedlichen Implementierungen erzeugt. Ich glaube, du meinst override die f(A x) Methode mit der f(B x) Methode. Überschreiben (per Wikipedia) ermöglicht einer Unterklasse oder untergeordneten Klasse, eine bestimmte Implementierung einer Methode bereitzustellen, die bereits von einer ihrer Oberklassen oder übergeordneten Klassen bereitgestellt wird.

Basierend auf der Überraschung in Ihrer Frage zum Ausdruck, ich glaube, Sie so etwas wie

@Override 
public void f(A x) { 
    System.out.println("Send an email to"+ x) ; 
} 
2
@Override 
public String toString() 
{ 
    return id; 
} 

Dies definiert, wie die Klasse ausgegeben wird gesucht. Wenn Sie eine Funktion wie die folgende aufrufen:

b.f(a) 

Sie geben eine Klasse als Parameter ein. Aufgrund Ihrer toString()-Methode, die eine Überschreibung der Standardmethode zur Ausgabe Ihrer Klasse darstellt, zeigen Sie die id nach Send an email to an.

1

Seit B erweitert A und A hat eine öffentliche Methode. So hat es die beiden folgenden Methoden -

public void f(A x){ 
    System.out.println("Send a fax to "+ x) ; 
} 

Und -

public void f(B x){ 
    System.out.println("Send an email to"+ x) ; 
} 

Tatsächlich ist die seond Methode in B ist eine überladene Version der Methode void f(A x) geerbt von A

2

ein Objekt der Klasse B hat beide f(A) und f(B). Wenn Sie f(x) aufrufen, wählt es im Allgemeinen das am genauesten eins, das dem Typ x entspricht. Dabei kommt es auf den Typ der Referenz an.

So ist Ihr a ein A, daher ruft es f(A). Ihr b ist ein B, daher ruft es f(B). Aber was ist dein ab? Der Typ der Referenz ist A. Der Compiler sagt also, dass er die f(A) Überladung aufrufen soll.

Aber dann sollte es das ab Objekt als A und daher gedruckt send a fax to A mit A.toString() anstatt B.toString() nicht verwendet?

Nein, weil die Wahl der Methode in diesem Fall nicht durch den Parameter bestimmt wird.Es ist keine Wahl zwischen Überladungen, wie die obige Wahl war, es ist eine Wahl zwischen überschreibt. Bei der Entscheidung, welche Methode zu verwenden ist, die von der Oberklasse oder die aus der Unterklasse, bestimmt der tatsächliche Typ des Objekts es. Da das Objekt, auf das sich ab bezieht, tatsächlich ein B ist, wird das toString() von B gewählt.

So - unter überladenen Methoden, die eine, die bestimmt wird, wird so gewählt, basierend auf der Anzahl und den Typ des Arguments und den Typ des Arguments ist die Art der Referenz .

Unter den Methoden außer Kraft gesetzt, ist diejenige, die im tatsächlichen Typ der Objektinstanz ausgewählt ist, unabhängig davon, um welchen Typ der Verweis es aufgerufen wird.

Beachten Sie, dass eine Methode nur überschrieben wird, wenn sie den gleichen Namen, die Anzahl der Parameter und die entsprechenden Parameter als übergeordnete Methode hat.