Questa è probabilmente una brutta cosa da fare, come discusso in Can parent and child class in Java have same instance variable?. (Cosa succede se il nome della variabile genitore è cambiato? Quindi non sarà più ombreggiato.) Tuttavia, sono ancora curioso di sapere se le variabili che sono statisticamente/non statiche si oscureranno a vicenda. Da un lato, mi sarei aspettato che fossero lo stesso nome di variabile, quindi sarebbe stato ombreggiato, ma d'altra parte sembra che il compilatore possa distinguere tra i due in base alla staticità.In Java, se una classe figlio ombreggia una variabile padre statica con una variabile figlio di istanza, quale variabile utilizzerà i metodi ereditati?
risposta
Da The Java Language Specification:
Se il nome di espressione consiste di un singolo Identifier, allora ci devono essere esattamente una dichiarazione visibile denota sia un locale variabile, parametro o campo nell'ambito nel punto in cui il Si verifica l'identificatore. In caso contrario, si verifica un errore in fase di compilazione.
Se la dichiarazione dichiara un campo finale, il significato del nome è il valore di quel campo. Altrimenti, il significato dell'espressione nome è la variabile dichiarata dalla dichiarazione.
Se un metodo in una superclasse fa riferimento a un particolare campo (statico o meno) di quella classe, solo la dichiarazione del campo di quella classe sarà in ambito in quel punto; qualsiasi campo (statico o altro) di sottoclassi non sarà incluso nell'ambito. Pertanto, il metodo utilizzerà sempre il campo della superclasse, anche se una sottoclasse lo eredita e ombreggia il campo.
Questa risposta è completamente riscritta in base alla mia nuova comprensione della domanda. Di seguito la mia prima risposta, tenuta per i posteri.
Da The Java Language Specification:
Una dichiarazione d di un campo, variabile locale, parametro del metodo, costruttore parametro parametro o al gestore delle eccezioni di nome n ombre le dichiarazioni di tutti gli altri campi, locali variabili, metodo parametri, parametri costruttore o parametri gestore eccezioni n che sono nel campo di applicazione nel punto in cui d si verifica in tutto l'ambito di d.
Ciò suggerisce che i compilatori sono obbligati a ombreggiare le variabili padre, indipendentemente dalla staticità.
Si noti che nessuno di questi è rilevante per ereditato dai metodi, che utilizzano sempre le variabili originali indipendentemente dal fatto che una sottoclasse li ombreggia. Sospetto che non sia questo che intendevi chiedere.
Questa è in realtà una risposta a ciò che stavo cercando di chiedere: "nulla di ciò è rilevante per i metodi ereditati, che usano sempre le variabili originali indipendentemente dal fatto che una sottoclasse li ombreggia". –
La specifica del linguaggio dice questo? Se sì, dove? Sto cercando di trovarlo. –
@DougTreadwell Sì, lo fa. Ho modificato la mia risposta. – Taymon
Guarda il codice qui sotto. Se si desidera accedere a field
da ChildClass
, verrà utilizzata la propria variabile membro. Se si desidera accedere allo statico field
da SuperClass
, è necessario chiamarlo in modo esplicito utilizzando SuperClass.field
. È possibile accedere direttamente a `STATIC_FIELD`` poiché non vi è alcuna ambiguità per il compilatore.
public class SuperClass{
static String field = "staticField1";
static String STATIC_FIELD = "staticField2";
//not possible to have a member field in this class -> compile error
//String field = "memberField"; is not possible
public SuperClass() {
System.out.println("field = " + field);
}
}
public class ChildClass extends SuperClass{
String field = "memberField";
public ChildClass() {
System.out.println("field = " + field);//access to member field
//need to explicitly call SuperClass.field to access the static variable
System.out.println("SuperClass.field = " + SuperClass.field);
//no need to do this when there is no amibiguity
System.out.println("STATIC_FIELD = " + STATIC_FIELD);
}
}
Capisco l'idea di shadowing, ma la parte importante della mia qusetion è "quale variabile erediterà i metodi usati?". –
Come da specifica del linguaggio Java:
Se la classe dichiara un campo con un certo nome, quindi la dichiarazione si dice che quel campo nasconda e tutte le dichiarazioni accessibili dei campi con lo stesso nome in superclassi e superinterfacce della classe.
Un campo nascosto si può accedere utilizzando un nome qualificato (se è statico)
sezione "Dichiarazioni di campo" si può fare riferimento.
Finora questa è una delle migliori risposte, ma sembra concentrarsi solo sullo shadowing. Non rimuoverei alcuna informazione, ma c'è qualcosa di aggiuntivo nelle specifiche che indicherebbe che i metodi ereditati usano anche i campi del bambino? –
Sembra che tu abbia una risposta per questo da Taymon. – kosa
+1 a questa risposta perché indica che è ancora possibile accedere al campo tramite il nome completo. – Bill
, a:
class Parent {
static String x="static in parent";
String y="instance in parent";
}
class Child extends Parent {
static String y="static in child";
String x="instance in child";
void foo() {
System.out.println("x "+x);
System.out.println("super.x " + super.x);
System.out.println("y "+y);
System.out.println("super.y " + super.y);
}
}
public class Main {
public static void main(String[] args) {
Parent parent=new Parent();
Child child=new Child();
System.out.println("Parent.x "+Parent.x);
System.out.println("parent.x "+Parent.x);
System.out.println("parent.y "+parent.y);
System.out.println("child.x "+child.x);
System.out.println("Child.y "+Child.y);
System.out.println("child.y "+child.y);
System.out.println("(Parent)child).x "+((Parent)child).x);
System.out.println("(Parent)child).y "+((Parent)child).y);
child.foo();
}
}
Parent.x static in parent
parent.x static in parent
parent.y instance in parent
child.x instance in child
Child.y static in child
child.y static in child
(Parent)child).x static in parent
(Parent)child).y instance in parent
x instance in child
super.x static in parent
y static in child
super.y instance in parent
Pubblica anche l'output, in modo che le persone possano apprendere ciò che fa, sia come commenti in-line sia come output incollato sotto – Bohemian
Capisco l'idea di shadowing, ma la parte importante del mio qusetion è "quale variabile erediterà i metodi usati? ". –
vedere le modifiche –
public class Test {
public static int MYNUMBER = 5;
public Test() {
}
}
public class TestChild extends Test {
public int MYNUMBER = 8;
public TestChild() {
}
}
public class Main {
public static void main(String[] args) {
TestChild testChild = new TestChild();
// This would print out 8
System.out.println("in main test child: " + testChild.MYNUMBER);
// This won't even compile if the MYNUMBER variable is overshadowed
// If the MYNUMBER variable is not overshadowed it
// would compile and
// print out 5
// If we make MYNUMBER static also on TestChild,
// it would compile and print out 8
System.out.println("in main TestChild.MYNUMBER " + TestChild.MYNUMBER);
// This would print out 5
System.out.println(Test.MYNUMBER);
}
}
Capisco l'idea di shadowing, ma la parte importante del mio qusetion è "quale variabile erediterà i metodi ?". –
I metodi ereditati useranno la variabile statica del genitore. Quindi se aggiungiamo alla classe Test il metodo: public int doSomething() { \t \t return MYNUMBER; \t} doSomething restituirà 5 in ogni momento. – Alex
Con il compilatore di Eclipse, i metodi della classe padre continueranno a utilizzare le variabili membro della superclasse, non le variabili ombreggiate della classe figlio, come mostrato di seguito. Questa è solo una versione leggermente modificata della risposta di thinksteep.
class Parent {
static String x ="static in parent";
String y="instance in parent";
void bar() {
System.out.println("x "+ x);
System.out.println("y "+ y);
}
}
class Child extends Parent {
static String y ="static in child";
String x="instance in child";
void foo() {
System.out.println("x "+x);
System.out.println("super.x " + super.x);
System.out.println("y "+y);
System.out.println("super.y " + super.y);
}
}
public class Main {
public static void main(String[] args) {
Parent parent=new Parent();
Child child=new Child();
System.out.println("Parent.x "+Parent.x);
System.out.println("parent.x "+Parent.x);
System.out.println("parent.y "+parent.y);
System.out.println("child.x "+child.x);
System.out.println("Child.y "+Child.y);
System.out.println("child.y "+child.y);
System.out.println("(Parent)child).x "+((Parent)child).x);
System.out.println("(Parent)child).y "+((Parent)child).y);
System.out.println("Member variable visibility in parent:");
parent.bar();
System.out.println("Member variable visibility in child:");
child.foo();
System.out.println("Member variable visibility in inherited methods:");
child.bar();
System.exit(0);
}
/* Output:
Parent.x static in parent
parent.x static in parent
parent.y instance in parent
child.x instance in child
Child.y static in child
child.y static in child
(Parent)child).x static in parent
(Parent)child).y instance in parent
Member variable visibility in parent:
x static in parent
y instance in parent
Member variable visibility in child:
x instance in child
super.x static in parent
y static in child
super.y instance in parent
Member variable visibility in parent methods:
x static in parent
y instance in parent
*/
- 1. impostazione di una variabile statica in Java
- 2. Variabile di istanza di annullamento dell'ereditarietà Java
- 3. Java -Che cos'è una variabile di istanza?
- 4. Perché mantenere una variabile statica?
- 5. Come posso creare una variabile locale statica in Java?
- 6. Accesso alle variabili di istanza private di padre dalla classe figlio?
- 7. inizializzazione variabile statica java
- 8. Assegnare una variabile statica prima di dichiarare
- 9. Riferimento indefinito a una variabile locale statica
- 10. Memorizzazione di una risorsa bitmap in una variabile statica
- 11. La classe genitore e figlio in Java può avere la stessa variabile di istanza?
- 12. inizializzazione di una variabile statica nell'intestazione
- 13. Come rendere una variabile statica thread-safe
- 14. Perché dichiarare una variabile statica in main?
- 15. Aggiungi una proprietà senza variabile di istanza?
- 16. Elimina record padre se figlio non presente
- 17. punto di avere una variabile di istanza come finale?
- 18. Inizializza una variabile di riferimento dei membri della classe, come se fosse una variabile regolare
- 19. Che cos'è una variabile di istanza?
- 20. Come convalidare se una stringa sarebbe una variabile java valida?
- 21. Lanciare una variabile usando una variabile Type
- 22. Variabile di istanza CoffeeScript
- 23. Funzione membro che restituisce una variabile statica
- 24. Confronto di una variabile con se stesso
- 25. Differenza tra la variabile istanza "@" appartenente all'oggetto classe e la variabile di classe "@@" in Ruby?
- 26. funzione statica e variabile statica e variabile
- 27. la variabile membro python di istanza funziona come variabile membro e alcuni funzionano come variabile statica
- 28. Restituisce classe figlio dalla classe padre
- 29. python: accesso a una variabile di istanza utilizzando un nome contenente una variabile
- 30. Scopri se esiste una variabile
sento che questa è una cosa importante da considerare e possono aiutare gli altri, in modo da questa domanda è d'uso, ma: ** Avete provato ** –
provarlo è una cosa, ma che può essere compilatore? dipendente. Mi chiedo se c'è una regola definitiva a riguardo nelle specifiche del linguaggio. –