2009-04-21 11 views
10

seguito è riportata una parte del mio codice per un progetto:Avendo 2 variabili con lo stesso nome in una classe che estende un'altra classe 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; 
    } 
} 

ho subito capito che facendo questo creerà due variabili all'interno la classe Body ha chiamato xe altre due variabili in Body chiamato y. Com'è possibile, e perché mai Java lo consente?

Suppongo che questo è il codice corretto di Classe corpo:

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; 
    } 
} 

Grazie per il vostro tempo

+0

Quindi, se ho un metodo con un parametro Point e invio un'istanza di Body della classe, sarò in grado di accedere alle variabili x e y dal punto dell'istanza? E se avessi il parametro di input sia di tipo Body che di Point, sarei in grado di accedere alle variabili x e y da Body? –

risposta

10

In un certo senso, modo si sostituisce i campi della classe eccellente. Ma è molto più facile da fare accidentalmente perché non c'è sovraccarico di campi (hai solo una variabile di un nome dato, il tipo non ha importanza). Questo è indicato come variabile 'nascondere' o 'ombreggiatura'. Quindi, hai ragione, finirai con due campi con lo stesso nome.

Il tuo secondo esempio è corretto. Sono ereditati dalla super-classe e poiché non sono dichiarati privati, sono visibili alla sottoclasse. In genere è una cattiva pratica riferirsi direttamente ai campi di una super classe e, a meno che non ci sia una buona ragione, dovrebbero dichiararli privati. Il tuo esempio di invocazione del super costruttore è l'approccio migliore.

Inoltre, se si nasconde un campo con un altro con lo stesso nome, è comunque possibile fare riferimento ad essi come super.x, super.y, rispetto a questo.x, this.y, si dovrebbe evitare questa situazione se in tutto possibile

+0

Quindi, se ho un metodo con un parametro Point, e invio un'istanza di Body della classe, sarò in grado di accedere alle variabili x e y da Point di quell'istanza? E se avessi il parametro di input sia di tipo Body che di Point, sarei in grado di accedere alle variabili x e y da Body? –

+0

@Martin Andersson si, dal momento che Point 'sa' solo x ogni y, e il tipo di parametro determina in che modo il codice 'vede' l'oggetto. Ovviamente potresti downcast Point p; Corpo b = ((Corpo) p); b.mass = xxx; Ma non farlo mai! ;-) –

1

Mi sono subito reso conto che facendo ciò creeremo due variabili all'interno della classe Body chiamata xe altre due variabili in Body chiamata y. Com'è possibile, e perché mai Java lo consente?

In realtà no, non si stanno creando due variabili con lo stesso nome, ovviamente un compilatore non dovrebbe e non lo consentirebbe.

Quello che sono facendo è shadowing le variabili esistenti definite come x e y, il che significa che Body.x e Body.y sono essenzialmente sovrappongono i nomi per Point.x e punto.Ý, rendendo completamente i due variabili quest'ultimo inaccessibile dalla classe Body (link to Java Language Specification definition of "shadowing").

Nome shadowing è generalmente percepire come una cattiva pratica e una causa di bug, e se si alza gli avvertimenti del compilatore javac, il compilatore doverosamente avvertire su questo.

+1

In realtà, è ancora possibile accedere a tali variabili, utilizzando Point.this.x e Point.this.y nella classe Body – Jorn

+1

Entrambe le variabili hanno lo stesso nome. Sono solo dichiarati in classi diverse. I nomi delle variabili sono solo "x" e "y", non "Body.x", "Body.y", "Point.x" e "Point.y". Anche il link che hai fornito sullo shadowing dice: "Alcune dichiarazioni possono essere ombreggiate in parte del loro ambito da un'altra dichiarazione con lo stesso nome [...]" - nota la parte "stesso nome". –

+0

J.S .: Penso che M.B. intendeva che fosse un codice descrittivo piuttosto che un codice eseguibile. –

5

Sì, avrete due variabili, con una che nasconde l'altra. Ha senso per consentire per due motivi:

  1. Supponiamo che hai una classe base Base e una classe derivata Derived cui l'autore di Base non ha alcuna idea circa. L'autore di Base non può mai aggiungere campi, solo perché una classe derivata potrebbe condividere i campi con? O dovrebbe Derived interrompere la compilazione quando la modifica a Base non influisce effettivamente sulla correttezza?
  2. I tuoi campi dovrebbero essere quasi sempre privati, a questo punto non importa se i nomi sono duplicati o meno - né "lato" conoscerà le variabili dell'altro.
4

seguito a ciò che altri hanno detto: È un BodyPoint? No, Body ha una proprietà posizione di tipo Point. Quindi, Body probabilmente non dovrebbe estendere Point. Se ti sbarazzi dell'eredità (dell'implementazione), ti libererai di molti problemi. Quello e utilizzare private (non protected!) E final liberamente.

+0

Mentre in generale "preferisci la composizione sull'ereditarietà" è buono, è anche possibile che il progettista desideri che Corpo abbia tutte le proprietà di Punto (presumibilmente ce ne sono altre che sono state omesse per chiarezza). – DJClayworth

Problemi correlati