2009-04-21 15 views
10

Folgende:2 Variablen mit dem gleichen Namen in einer Klasse zu haben, das für ein Projekt ein Teil meines Codes erstreckt, ist eine andere Klasse in Java

public class Body extends Point{ 
    public double x, y, mass; 

    public Body() { 
     x = y = mass = 0; 
    } 

    public Body(double x, double y, double mass) { 
     this.mass = mass; 
     this.x = x; 
     this.y = y; 
    } 
} 

public class Point { 
    public double x; 
    public double y; 

    public Point(double x, double y) { 
     this.x = x; 
     this.y = y; 
    } 
} 

ich, dass dies schnell realisiert dabei innerhalb zwei Variablen schaffen Die Body-Klasse heißt x und zwei andere Variablen in Body namens y. Wie ist das überhaupt möglich, und warum in aller Welt lässt Java das überhaupt zu?

Ich nehme an, dies der richtige Code der Klasse Körper ist:

public class Body extends Point{ 
    public double mass; 

    public Body() { 
     super(); 
     mass = 0; 
    } 

    public Body(double x, double y, double mass) { 
     super(x,y); 
     this.mass = mass; 
    } 
} 

Vielen Dank für Ihre Zeit

+0

Also, wenn ich eine Methode mit einem Point-Parameter habe und ich eine Instanz der Klasse Body einsende, kann ich auf die x- und y-Variablen vom Point dieser Instanz zugreifen? Und wenn ich den Eingabeparameter vom Typ Körper anstelle von Punkt hätte, wäre ich nur in der Lage, auf die x- und y-Variablen von Body zuzugreifen? –

Antwort

10

Gewissermaßen Sie zwingende Felder der Superklasse. Aber es ist viel einfacher, versehentlich zu tun, weil es keine Überladung von Feldern gibt (Sie haben nur eine Variable eines bestimmten Namens, der Typ spielt keine Rolle). Dies wird als Variable "Verstecken" oder "Verschattung" bezeichnet. Sie haben also Recht, Sie erhalten zwei Felder mit demselben Namen.

Ihr zweites Beispiel ist korrekt. Sie werden von der Superklasse geerbt, und da sie nicht als privat deklariert sind, sind sie für die Unterklasse sichtbar. Es ist im Allgemeinen eine schlechte Übung, direkt auf die Felder einer Superklasse zu verweisen, und wenn es keinen guten Grund gibt, sollten sie als privat deklariert werden. Ihr Beispiel für den Aufruf des Superkonstruktors ist der beste Ansatz.

Wenn Sie ein Feld mit einem anderen mit demselben Namen ausblenden, können Sie immer noch auf sie als super.x, super.y, vs. this.x, this.y verweisen, sollten Sie diese Situation vermeiden, wenn alles möglich.

+0

Also, wenn ich eine Methode mit einem Point-Parameter habe, und ich sende eine Instanz der Klasse Body, kann ich auf die x- und y-Variablen vom Point dieser Instanz zugreifen? Und wenn ich den Eingabeparameter vom Typ Körper anstelle von Punkt hätte, wäre ich nur in der Lage, auf die x- und y-Variablen von Body zuzugreifen? –

+0

@Martin Andersson Ja, da Punkt nur über x jedes y "weiß", und du bist Parameter-Typ bestimmt, wie Ihr Code das Objekt "sieht". Du könntest Point p natürlich reduzieren; Körper b = ((Körper) p); b.masse = xxx; Aber tu das nie! ;-) –

1

Ich erkannte schnell, dass dies zwei Variablen in der Body-Klasse namens x und zwei andere Variablen in Body namens y erstellen wird. Wie ist das überhaupt möglich, und warum in aller Welt lässt Java das überhaupt zu?

Eigentlich nein, Sie erstellen nicht zwei Variablen mit dem gleichen Namen, offensichtlich sollte ein Compiler nicht und würde dies nicht zulassen.

Was Sie sind Dadurch könnte die vorhandenen Variablen wie x und y definiert ist Shadowing, was bedeutet, dass Body.x und Body.y sind im Wesentlichen die Namen für point.x und point.y überlappen, wobei die beiden letzteren Variable machen vollständig unzugänglich von der Body-Klasse (link to Java Language Specification definition of "shadowing").

Name Shadowing wird im Allgemeinen als eine schlechte Praxis und eine Ursache von Fehlern, und wenn Sie die Warnungen des Javac-Compilers auftauchen, warnt der Compiler pflichtgemäß Sie darüber.

+1

Tatsächlich können Sie immer noch auf diese Variablen zugreifen, indem Sie Point.this.x und Point.this.y in der Body-Klasse – Jorn

+1

verwenden. Beide Variablen haben denselben Namen. Sie sind nur in verschiedenen Klassen deklariert. Die Namen der Variablen sind nur "x" und "y", nicht "Body.x", "Body.y", "Point.x" und "Point.y". Selbst der Link, den Sie über das Shadowing gegeben haben, sagt: "Einige Deklarationen können in einem Teil ihres Geltungsbereichs durch eine andere gleichnamige Deklaration beschattet werden [...]" - beachten Sie den "gleichen Namen" -Teil. –

+0

J.S .: Ich denke M.B. beabsichtigt, dass dies beschreibender und nicht ausführbarer Code ist. –

5

Ja, Sie haben zwei Variablen, von denen eine die andere versteckt. Es macht Sinn, es aus zwei Gründen zu erlauben:

  1. Angenommen, Sie eine Basisklasse Base und eine abgeleitete Klasse haben Derived, die der Autor von Base keine Ahnung hat. Sollte der Autor von Base nie in der Lage sein, Felder hinzuzufügen, nur weil eine abgeleitete Klasse könnte teilen die Felder? Oder sollte Derived aufhören zu kompilieren, wenn die Änderung zu Base nicht wirklich die Korrektheit betrifft?
  2. Ihre Felder sollten fast immer privat sein, zu welchem ​​Zeitpunkt es egal ist, ob die Namen dupliziert sind oder nicht - keine "Seite" wird über die Variablen der anderen wissen.
4

Weiter zu dem, was andere gesagt haben: Ist Body ein Point? Nein, Body hat eine Positionseigenschaft des Typs Point. So sollte Body wahrscheinlich nicht Point verlängern. Wenn Sie die Vererbung (der Implementierung) loswerden, werden Sie viele Probleme los. Das und verwenden Sie private (nicht protected!) Und final großzügig.

+0

Während im Allgemeinen "Komposition über Vererbung bevorzugen" gut ist, ist es auch möglich, dass der Designer möchte, dass Body alle Eigenschaften von Point hat (vermutlich gibt es andere, die der Übersichtlichkeit halber weggelassen wurden). – DJClayworth