2012-12-31 2 views
5

Ich suchte online nach ähnlicher Frage, aber konnte es nicht finden. Also, hier posten.Java-Vererbung - dieses Schlüsselwort

In dem folgenden Programm, warum der Wert von 'i' als 100 gedruckt wird?

AFAIK 'dies' bezieht sich auf das aktuelle Objekt; In diesem Fall ist 'TestChild' und der Klassenname wird ebenfalls korrekt gedruckt. Aber warum ist der Wert der Instanzvariable nicht 200?

public class TestParentChild { 
    public static void main(String[] args) { 
     new TestChild().printName(); 
    } 
} 

class TestChild extends TestParent{ 
    public int i = 200; 
} 

class TestParent{ 
    public int i = 100; 
    public void printName(){ 
     System.err.println(this.getClass().getName()); 
     System.err.println(this.i); //Shouldn't this print 200 
    } 
} 

Und außerdem ist die Ausgabe der folgenden wie erwartet. Die Kindklassenmethode wird aufgerufen, wenn ich "this.test()" von der Elternklasse anrufe.

public class TestParentChild { 
    public static void main(String[] args) { 
     new TestChild().printName(); 
    } 
} 

class TestChild extends TestParent{ 
    public int i = 200; 
    public void test(){ 
     System.err.println("Child Class : "+i); 
    } 

} 

class TestParent{ 
    public int i = 100; 
    public void printName(){ 
     System.err.println(this.getClass().getName()); 
     System.err.println(this.i); //Shouldn't this print 200 
     this.test(); 
    } 
    public void test(){ 
     System.err.println("Parent Class : "+i); 
    } 
} 

Antwort

7

Java hat keine virtuellen Felder, so dass das i Feld in printName bezieht sich immer auf TestParent.i und keinen Nachkommen Kind.

Polymorphismus durch Vererbung in Java geschieht nur mit Methoden, also wenn Sie das Verhalten möchten Sie beschreiben, dann würden Sie dies wünschen:

class TestChild extends TestParent{ 

    private int i = 200; 

    @Override 
    public int getI() { return this.i; } 
} 

class TestParent{ 

    private int i = 100; 

    public int getI() { return this.i; } 

    public void printName(){ 
     System.err.println(this.getClass().getName()); 
     System.err.println(this.getI()); // this will print 200 
    } 
} 
+0

Danke für die prompte Antwort außer Kraft setzen nur . Könnten Sie bitte grübeln, was meinst du damit? ** "In Java können Felder nicht als virtuell markiert werden" ** Wie bereits erwähnt, wird die Instanzmethode in meinem zweiten Programm korrekt aufgerufen. Die Instanzvariable bezieht sich jedoch auf die Klasse Parent. – Jack

+0

Ich habe meine Antwort aktualisiert. – Dai

+1

In Java sind alle Methoden (sofern nicht anders angegeben) "virtuell", was bedeutet, dass sie eine verknüpfte vtable haben, die den Runtime-Versand ermöglicht. Felder existieren jedoch als absolute (ish) Speicherstelle und werden nicht durch irgendeine vtable ausgeglichen. Ich mache die Verwirrung auf Javas Design-Dokument verantwortlich, das nicht explizite "virtuelle" und "überschreiben" Schlüsselwörter hat, während C# dies tut. – Dai

2

Da Felder in Java werden nicht vererbt. Mit Ihren Deklarationen haben Sie effektiv zwei verschiedene Felder mit dem Namen i deklariert, und Instanzen von TestChild haben beide. Wenn TestParent kompiliert wird, verweisen Verweise auf i in seinen Methoden immer auf TestParent.i.

+2

Felder werden vererbt, nur nicht überschrieben. – Dai

+0

Sicher, das ist besser zu formulieren. – Dolda2000

2

Es gibt keine Möglichkeit, eine Klassenvariable zu überschreiben.

Sie überschreiben keine Klassenvariablen in Java, sondern verbergen sie. Überschreiben ist zum Beispiel Methoden und Verbergen unterscheidet sich von Überschreiben.

In dem Beispiel, das Sie angegeben haben, verbergen Sie die Klassenvariable mit dem Namen 'i' in Klasse TestChild, die sie von ihrer Oberklasse TestParent mit dem gleichen Namen 'i' geerbt hätte. eine Variable auf diese Weise versteckt nicht den Wert der Klassenvariablen beeinflussen ‚i‘ in der übergeordneten Klasse TestParent

das gewünschte Verhalten zu erhalten, können Sie die getI() Methode

class TestChild extends TestParent{ 

    private int i = 200; 

    @Override 
    public int getI() { 
     return this.i; 
    } 
} 
+0

Vielen Dank für Ihre Antwort. Ich hatte über das Verstecken gelesen, aber vergessen. :(Danke nochmal. – Jack

+0

Gern geschehen :) – Rahul

Verwandte Themen