2009-01-30 11 views
5

Ich habe eine Frage zu Vererbung und Casting in Java. Ich habe die folgenden zwei Beispiel-Klassen und eine Testklasse, und ich feststellen, meine Frage nach den Klassen:Vererbung und Casting in Java

public class Automobile { 
    public int var; 

    public Automobile() { 
     var = 1; 
    } 

    public String toString() { 
     return "AUTOMOBILE: " + var; 
    } 
} 


public class Porsche extends Automobile { 
    public int var; 

    public Porsche() { 
     var = 2; 
    } 

    public String toString() { 
     return "PORSCHE: " + var; 
    } 
} 

public class Test { 
    public static void main (String [] args) { 
     Porsche p = new Porsche(); 
     Automobile a = new Automobile(); 

     System.out.println ("(Automobile) p = " + (Automobile)p); 

     System.out.println ("(Automobile) p.var = " + ((Automobile)p).var); 
    } 
} 

Die Ausgabe lautet:

(Automobile) p = PORSCHE: 2 
(Automobile) p.var = 1 

Ich verstehe nicht, in der zweiten Erklärung, warum wir habe 1. Sollte es nicht 2 sein? Denn nachdem ich in der ersten Anweisung p zu Automobil-Guss noch ich PORSCHE: 2 als die Darstellung von p bekommen - ich verstehe dies auf folgende Weise:

trotzdem habe ich p zu Automobil-p hält seine „ursprüngliche Natur“ gecastet - p ist ein Objekt der Klasse Porsche, aber weil Porsche Automobile erweitert, könnten wir sagen, dass p auch ein Automobil ist. Und wenn wir es explizit auf Automobile anwenden, verwendet es weiterhin seine Methoden - in unserem Fall die in Porsche definierte Methode toString().

Auf der anderen Seite, wenn das, was ich schreibe, ist korrekt, dann die zweite print-Anweisung sollte 2 geben und nicht 1.

scheint nun dies als Widerspruch zu mir, aber da dies in Java arbeitet, wie es scheint dass ich nicht verstehe, was während des Castings und des Vererbungsprozesses passiert.

Antwort

16

Ich glaube, dass Sie Variablen in Java tatsächlich nicht überschreiben können. Die Unterklasse "versteckt" die Variable var.

Wenn Sie in Automobile umwandeln, erhalten Sie die Superklassenversion der var Variablen. Die Methode toString() sucht jedoch immer noch nach der Instanzversion der var-Variablen.

Wenn Sie die public int var aus der Porsche Unterklasse entfernt haben, sollte es wie erwartet funktionieren.

Es sollte angemerkt werden, dass es keine gute Praxis ist, öffentliche Instanzvariablen zu verwenden. Sie sollten Getter/Setter immer so erstellen, dass sie die richtigen encapsulation haben.

5

Verschattung der Variablen var.

Ihre Porche.var ist eine andere Variable als die Automobile.var.

Die Porsche.toString()-Methode verwendet Porsche.var, während der Cast den Compiler anweist, die Automobile-Version zu verwenden.

2

Der Zugriff auf Felder ist nicht polymorph - sie hängt nur vom Kompilierzeittyp des Ausdrucks ab.

Der Ausdruck ((Automobil) p) hat Kompilierungszeit Typ Automobile, so dass seine Felder verwendet werden.

1

Wenn die Variable "var" in beiden Klassen deklariert wird, werden tatsächlich zwei Felder im Speicher erstellt.

Eine Instanz von "Porsche" wird zwei "var" -Felder im Speicher haben, eine der "Porsche" -Klasse und eine der Superklasse "Automobile". Das Feld "var" der Superklasse wird ausgeblendet, wenn Sie von einer bekannten "Porsche" -Instanz auf "var" verweisen.Wenn Sie diese Instanz in "Auto" umwandeln und auf das Feld "var" verweisen, verweisen Sie auf das Feld "Var" des "Automobils".

Es gibt kein Überschreiben in Feldern. Neue Felder mit demselben Namen überschatten die Felder der Superklasse.

Um das erwartete Ergebnis zu erhalten, sollten Sie kein "var" -Feld in der Klasse "Porsche" deklarieren.

0

jedoch:

Wenn Sie eine Methode, die ein Objekt übergeordnete Klasse zurückgibt, kann es zurückgeben jedes Objekt eine Klasse geben, die es (Beispiel Fabrik) erstreckt. Wenn diese Methode ein Objekt der Subklasse B zurückgibt und Sie es nicht als B-Objekt darstellen, werden alle Attribute als übergeordnete Attribute verwendet. Wenn Sie es in B umwandeln, sind seine Attribute A- und B-Attribute.

class A { 
int a1,a2; 
public A(){} 


    public static A getInstance() { 
    return new B() ; 
    } 
} 
class B { 
int b1,b2; 
    public B() {} 

} 
class Test{ 

public static void main (String [] args) { 

    A theA = A.getInstance() ; //here theA has only a1,a2 as attributes 
    B theB = (B)theA // here theB has b1,a2 and a1,a2 as attributes 
    } 


}