Sovrascrivere le variabili membro in Java

Sto studiando l’override delle funzioni membro in JAVA e ho pensato di sperimentare con l’override delle variabili membro.

Quindi, ho definito le classi

public class A{ public int intVal = 1; public void identifyClass() { System.out.println("I am class A"); } } public class B extends A { public int intVal = 2; public void identifyClass() { System.out.println("I am class B"); } } public class mainClass { public static void main(String [] args) { A a = new A(); B b = new B(); A aRef; aRef = a; System.out.println(aRef.intVal); aRef.identifyClass(); aRef = b; System.out.println(aRef.intVal); aRef.identifyClass(); } } 

L’output è:

 1 I am class A 1 I am class B 

Non sono in grado di capire perché quando aRef è impostato su b intVal è ancora di class A?

Quando si crea una variabile con lo stesso nome in una sottoclass, si parla di hide . La sottoclass risultante ora avrà entrambe le proprietà. Puoi accedere a quello dalla superclass con super.var o ((SuperClass)this).var . Le variabili non devono nemmeno essere dello stesso tipo; sono solo due variabili che condividono un nome, proprio come due metodi sovraccaricati.

Le variabili non sono polimorfiche in Java; non si escludono a vicenda.

Le variabili vengono risolte in fase di compilazione, i metodi di esecuzione. L’aRef è di tipo A, quindi aRef.Intvalue è in fase di compilazione risolta a 1.

Non esiste alcun polimorfismo per i campi in Java.

Variables decisione delle Variables avviene in un momento di compilazione, quindi sarà sempre ansible accedere alle variabili della class base (non alle variabili ereditate dal bambino).

Quindi, ogni volta che succede upcasting, ricorda sempre

1) Si accederà alle variabili della class base.

2) Verranno chiamati i metodi di sottoclass (i metodi sovrascritti se si esegue l’override per altri metodi ereditati dal genitore).

Da JLS Java SE 7 Edition §15.11.1:

Questa mancanza di ricerca dynamic per gli accessi sul campo consente ai programmi di funzionare in modo efficiente con implementazioni dirette. Il potere del late binding e override è disponibile, ma solo quando vengono utilizzati i metodi di istanza.

Le risposte di Oliver Charlesworth e Marko Topolnik sono corrette, mi piacerebbe approfondire un po ‘il perché della parte della domanda:

In Java i membri della class sono accessibili in base al tipo di riferimento e non al tipo dell’object reale. Per lo stesso motivo, se avessi un someOtherMethodInB() nella class B , non saresti in grado di accedervi da aRef dopo che aRef = b è stato eseguito. Gli identificatori (cioè nomi di classi, variabili, ecc.) Vengono risolti in fase di compilazione e quindi il compilatore si affida al tipo di riferimento per farlo.

Ora nel tuo esempio, quando System.out.println(aRef.intVal); stampa il valore di intVal definito in A perché questo è il tipo di riferimento utilizzato per accedervi. Il compilatore vede che aRef è di tipo A e che è l’ intVal cui accederà. Non dimenticare che hai entrambi i campi nelle istanze di B JLS ha anche un esempio simile al tuo, “15.11.1-1. Legame statico per accesso al campo” se vuoi dare un’occhiata.

Ma perché i metodi si comportano diversamente? La risposta è che per i metodi, Java utilizza l’ associazione tardiva . Ciò significa che al momento della compilazione, trova il metodo più adatto per la ricerca durante il runtime. La ricerca riguarda il caso in cui il metodo viene sovrascritto in alcune classi.

OverRide Concept in Java Le funzioni sovrascrivono in base al tipo di object e alle variabili a cui si accede sul tipo di riferimento.

  1. Funzione Override: in questo caso, supponiamo che una class genitore e figlio abbiano entrambi lo stesso nome di funzione con una propria definizione. Ma quale funzione verrà eseguita dipende dal tipo di object non sul tipo di riferimento in fase di esecuzione.

Ad esempio:

 Parent parent=new Child(); parent.behaviour(); 

Qui parent è un riferimento della class Parent ma contiene un object di class figlio, ecco perché in questo caso verrà chiamata la funzione class figlio.

 Child child=new Child(); child.behaviour(); 

Qui il child tiene un object di class figlio, quindi verrà chiamata la funzione class figlio.

 Parent parent=new Parent(); parent.behaviour(); 

Qui il parent mantiene l’object della class genitore, quindi verrà chiamata la funzione della class genitore.

  1. Sostituisci variabile: Java supporta variabili sovraccariche. Ma in realtà si tratta di due variabili diverse con lo stesso nome, una nella class genitore e una nella class figlio. E entrambe le variabili possono essere dello stesso tipo di dati o differenti.

Quando si tenta di accedere alla variabile, dipende dall’object del tipo di riferimento, non dal tipo di object.

Ad esempio:

 Parent parent=new Child(); System.out.println(parent.state); 

Il tipo di riferimento è padre, quindi è ansible accedere alla variabile della class padre, non alla variabile della class figlio.

 Child child=new Child(); System.out.println(child.state); 

Qui il tipo di riferimento è Child, quindi la variabile della class Child non è accessibile dalla variabile della class Parent.

 Parent parent=new Parent(); System.out.println(parent.state); 

Qui il tipo di riferimento è padre, quindi è ansible accedere alla variabile della class padre.

Bene, spero tu abbia la risposta. In caso contrario, puoi provare a vedere nella modalità di debug. la sottoclass B ha accesso a intVal. Non sono polimorfici, quindi non vengono sovrascritti.

Se usi il riferimento di B, otterrai intVal di B. Se si usa il riferimento di A, si otterrà l’intVal di A. È così semplice.

Secondo le specifiche Java, le variabili di istanza non vengono sovrascritte da una super class da una sottoclass quando viene estesa.

Quindi la variabile nella sottoclass può essere vista come una che condivide lo stesso nome.

Inoltre, quando il costruttore di A viene chiamato durante la creazione dell’istanza di B, la variabile (intVal) viene inizializzata e quindi l’output.

Spero che questo possa aiutare

 public class B extends A { // public int intVal = 2; public B() { super(); super.intVal = 2; } public void identifyClass() { System.out.println("I am class B"); } } 

Java ha una piuma di incapsulamento significa che lega strettamente la proprietà e il comportamento di un object. quindi solo tramite un riferimento di class possiamo chiamare il suo comportamento per cambiarne la proprietà.

e nell’ereditarietà solo il metodo esegue l’override in modo che possa influenzare solo la sua proprietà.