perché la variabile di istanza di super-class non è sovrascritta nel metodo sub class

Perché la variabile di istanza di super-class non è sovrascritta nel metodo sub-class vedi il mio codice qui sotto..in quale metodo viene sovrascritto la stampa ma la variabile a no. e perché il codice consente di scrivere variabili duplicate in sottoclass ..

class B { int a=10; public void print() { System.out.println("inside B super class"); } } class C extends B { int a=20; public void print() { System.out.println("inside C sub class"); } } public class A { public static void main(String[] args) { B b=new C(); b.print();//it will print inside c sub class System.out.println(ba);//it will print super class variable value=10 } } 

Perché la variabile di istanza di super class non è sovrascritta nel metodo sub class vedi il mio codice qui sotto …

Perché le variabili di istanza NON possono essere sovrascritte in Java 1 . Solo in Java i metodi possono essere sovrascritti.

Quando si dichiara un campo con lo stesso nome di un campo esistente in una superclass, il nuovo campo nasconde il campo esistente. Il campo esistente della superclass è ancora presente nella sottoclass e può anche essere utilizzato … in base alle normali regole di accesso Java.


1 – Perché? 1) Perché le variabili prioritarie rompono l’astrazione di class. Ad esempio, se un override cambia il tipo della variabile, è probabile che cambi (interrompa) il comportamento dei metodi nella class genitore che ha usato la variabile originale. 2) Perché non raggiungerebbe nulla che non possa essere fatto in altri modi … meglio. Ad esempio, un buon design dichiara tutte le variabili di istanza come private e fornisce getter / setter per loro come richiesto. I getter / setter possono essere sovrascritti e la class genitore può “proteggersi” da eventuali sostituzioni indesiderate utilizzando direttamente i campi privati ​​o dichiarando i getter / setter final .

Riferimenti:

  • Java Tutorial – Nascondere i campi
  • Esempio JLS 8.3.1.1-3 – Nascondere i campi delle istanze .

È ansible fare riferimento alla seguente sezione / esempi nelle specifiche del linguaggio Java che spiegano l’argomento.

  1. Esempio 8.3.1.1-3. Nascondere le variabili di istanza
  2. Sezione 8.4.8. Ereditarietà, sovrascrittura e occultamento e esempi correlati

Il resto del mio post è un’informazione aggiuntiva per coloro che sono interessati a grattare la superficie degli interni di jvm su questo argomento. Possiamo iniziare esaminando i codici byte generati per la class A usando javap. In seguito disassembla i codici byte in un testo leggibile basato su istruzioni (mnemonici).

 javap -c A.class 

Senza perdersi in molti dettagli dell’intero dis-assembly, possiamo concentrarci sulle linee corrispondenti a b.print e ba

 9: invokevirtual #4 // Method B.print:()V ... ... 16: getfield #6 // Field Ba:I 

Possiamo immediatamente dedurre che i codici op utilizzati per accedere al metodo e una variabile sono diversi. Se provieni da una scuola C ++, puoi percepire che tutte le chiamate ai metodi sono virtuali per impostazione predefinita in java.

Ora scriviamo un’altra class A1 identica ad A, ma abbiamo appena un casting per accedere alla variabile ‘a’ in C.

class pubblica A1 {
public static void main (String [] args) {
B b = nuovo C ();
b.print (); // casting è irrilevante qui perché i metodi sono comunque vincolati al runtime System.out.println (((C) b) .a); // il casting ci consente di accedere al valore di a in C
}
}

Compilare il file e disassemblare la class.

javap -c A1.class

Noteresti che dis-assembly ora punta a Ca invece di Ba

19: getfield # 6 // Field Ca: I

se vuoi approfondire questo argomento, ecco ulteriori informazioni:
– invokevirtual corrisponde all’opcode 0xb6
– getfield corrisponde all’opcode 0xb4

È ansible trovare una specifica JVM che spiega esaurientemente su questi codici opzionali all’indirizzo: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html
Consulta su amazon.com i libri “Java Virtual Machine” che potrebbero rendere la vita un po ‘più semplice per decodificare le specifiche.

Ho modificato il tuo codice per una spiegazione semplice, invece della variabile ‘a’, diciamo che la class C contiene la variabile ‘c’. È per lo stesso motivo per cui la class C non può accedere alla variabile di istanza di Class c stessa senza Typecasting. Esempio indicato di seguito

 class B { int a=10; public void print() { System.out.println("inside B super class"); } } class C extends B { int x=20; public void print() { System.out.println("inside C sub class"); } } public class A { public static void main(String[] args) { B b=new C(); System.out.println(bx);//will throw compile error unless b is type casted to Class C } } 

Quindi, in java, il compilatore fa riferimento al riferimento, non all’istanza. Per superare questo compilatore usa il polimorfismo Runtime , ma è per i metodi, non per le variabili di istanza. Quindi non è ansible accedere alle variabili senza il cast di tipi e i metodi, a meno che, sovrascritto (polymoprhism di runtime), non sia ansible accedere senza digitare cast.

Quindi, nel nostro caso, è ovvio per la refrenza di Superclass che trasporta un’istanza di sottoclass, da visualizzare nella superclass.

Poiché le variabili di istanza non vengono sovrascritte in java, non vi è alcun polimorfismo di runtime associato ad esse e quindi al momento della compilazione viene deciso per riferimento.

Nel tuo codice

 B b = new C(); b.print(); As b is of type Class B which is Parent to C and hence as there is no run time polymorphism it is decided at compile time to call instance variable of Class B. 

Ecco la mia prospettiva a livello di progettazione / concettuale sul perché le variabili di istanza non sono sovrascritte. Per semplificare, se consideriamo le classi astratte, definiscono metodi astratti e si aspettano che vengano sovrascritte. Non c’è mai stato nulla di simile a variabili astratte . Se esistesse, allora potremmo aspettarci che il linguaggio lo supporti superando. Quindi, quando viene progettata una class astratta, il progettista definisce uno stato comune comune e un comportamento comune (inclusi i metodi astratti) per i sottotipi. Quasi sempre se lo stato deve essere ereditato (accesso protetto), allora sarebbe semplicemente ereditato e credo che in pochissimi casi alcuni di essi potrebbero essere ridefiniti, ma molto raramente ri-dichiarati. Quindi, ci si aspetta che lo stato venga semplicemente ereditato mentre si prevede che il comportamento sia ereditato e sovrascritto.