2010-08-17 16 views
11

Warum wird zuletzt gedruckt "Ich bin eine Kindklasse." ?Java-Vererbung

public class Parent 
{ 
    String parentString; 
    public Parent() 
    { 
     System.out.println("Parent Constructor."); 
    } 

    public Parent(String myString) 
    { 
     parentString = myString; 
     System.out.println(parentString); 
    } 

    public void print() 
    { 
     System.out.println("I'm a Parent Class."); 
    } 
} 

public class Child extends Parent 
{ 
    public Child() { 
     super("From Derived"); 
     System.out.println("Child Constructor."); 
    } 

    public void print() 
    { 
     super.print(); 
     System.out.println("I'm a Child Class."); 
    } 

    public static void main(String[] args) 
    { 
     Child child = new Child(); 
     child.print(); 
     ((Parent)child).print(); 
    } 
} 

Ausgang:

From Derived 

Child Constructor. 

I'm a Parent Class. 

I'm a Child Class. 

I'm a Parent Class. 

I'm a Child Class. 

Antwort

15

Da dies ein Beispiel für polymorphism ist (späte Bindung). Zur Kompilierzeit geben Sie an, dass das Objekt vom Typ Parent ist und daher nur Methoden aufrufen kann, die in Parent definiert sind. Aber zur Laufzeit, wenn die "Bindung" passiert, wird die Methode für das Objekt aufgerufen, das vom Typ Child ist, egal wie es im Code referenziert wird.

Der Teil, der Sie überrascht, ist, warum die überschreibende Methode zur Laufzeit aufgerufen werden sollte. In Java (im Gegensatz zu C# und C++) sind alle Methoden virtual und daher wird die überschreibende Methode aufgerufen. Siehe this example, um den Unterschied zu verstehen.

+1

Gute Frage und gute Antwort. Dies ist auch eine gute Sache in realen Programmen; Ihr Code könnte kaputt gehen, wenn Sie zufällig einen Code hatten, der die übergeordnete Implementierung aufgerufen hat. – Tormod

2

Beide:

child.print(); 

und

((Parent)child).print(); 

Sollte zurück:

I'm a Parent Class. 
I'm a Child Class. 

In dieser Reihenfolge.

Das Umwandeln eines Objekts in seine Basisklasse ändert nicht, welcher Methodenaufruf ausgeführt wird.

In diesem Fall wird auch nach dem Cast die Child-Druckmethode aufgerufen und nicht die Parent-Methode.

+0

Was mich verwirrte war, dass der gleiche Code in C# nur "Ich bin Elternklasse" druckt – vad

+0

Vererbung und Polymorphie funktioniert genau so in C#. C# erfordert jedoch das virtuelle Schlüsselwort für Methoden, die Sie beim Erben von Unterklassen außer Kraft setzen wollen, also nehme ich an, dass Sie nicht virtuell verwendet haben, daher haben Sie das andere Ergebnis. – vicsz

0

Auch wenn Sie child in Parent umwandeln, ändert sich die Implementierung der Methode nicht. Dies macht es nicht wirklich zu einem Elternteil. Aus diesem Grunde kann man so etwas tun:

Image img = new BufferedImage(...); 

Obwohl Bild ist abstrakt img noch unter einem BufferedImage ist.

0

Auch wenn Sie es als Elternklasse einstufen, heißt das nicht, dass es die Funktionen seiner Eltern verwendet - es behandelt nur das Objekt als Elternteil.

Mit ((Eltern) Kind) .print(); Sie sagen "Behandle dieses Objekt als übergeordnetes Objekt, nicht als untergeordnetes Objekt". Nicht "Verwenden Sie die übergeordnete Methodenimplementierungen"

Wenn das untergeordnete Objekt also über andere Methoden verfügte, wären Sie nicht in der Lage, sie aufzurufen. Aber da print() eine Methode des Elternteils ist, kann man sie trotzdem aufrufen, aber sie verwendet die Implementierung des tatsächlichen Objekts (nicht die Klasse, die es erzeugt).

0

In Java rufen wir eine Methode für ein Objekt auf, dann ruft sie die Methode auf, indem sie das unterste Objekt verwendet ............... hier:

Objekt | | Eltern | | Child < - sub meist Objekt

Fall 1 ::

Kind Kind = new Kind();

child.print(); 

diese Berufung Kind Klassenmethode Druck von Kind-Objekt ... Kind sub meisten so druckt er

Ausgabe ::

Ich bin ein Elternteil Klasse. Ich bin eine Kinderklasse.

Erläuterung: Von der Child-Methode ruft die Parent-Methode wegen super.print() auf; Methode so erste Zeile ist ich eine Elternklasse. Nach Abschluss der übergeordneten Methode Ausführungssteuerungen kommt zurück zu Kind-Methode und druckt Ich bin eine Kind-Klasse.

Fall 2 ::

((Parent)child).print(); 
if we call like this jvm calls print() method by using sub most object here sub most object is child object so it prints 

output:: 
      I'm a Parent Class. 
      I'm a Child Class. 

Erläuterung: Von Kind Methode es wegen super.print Mutter Methode ruft(); Methode so erste Zeile ist ich eine Elternklasse. Nach Abschluss der übergeordneten Methode Ausführungssteuerungen kommt zurück zu Kind-Methode und druckt Ich bin eine Kind-Klasse.