Usando la parola chiave super per accedere ai membri di super-classe

0

Ho le seguenti domande sulla parola chiave super in java:

Ho un codice qui sotto con le classi:

  • A Estendi nessuna classe contiene la variabile intera i
  • B Estende la classe A contiene la variabile intera i
  • C Estende la classe B contiene la variabile intera i

     class A {
        int i = 20;
    
        A() {
            System.out.println("I am in constructor of the parent class");
        }
    }
    
    class B extends A {
        int i = 30;
    
        B() {
            System.out.println("I am in constructor of the subclass");
        }
    }
    
    class C extends B {
        int i = 40;
    
        C() {
            System.out.println("I am in constructor of the main class");
        }
    
        void display() {
            System.out.println(i);
            System.out.println(super.i);
            /*
             * My first thoughts to access the third variable 'i'
             * inherited indirectly to this class by 'class A'.
             * I thought that it would print 20 :(.
               System.out.println(super.super.i);
             */ 
        }
    
        public static void main(String[] argue) {
            C obj2 = new C(); 
            obj2.display();
        }
    }
    
    1. Ora come classe B eredita la classe A quindi deve avere due variabili integer i . La classe C eredita la classe B quindi avrà due variabili integer da B e una definita in sé.

Ora posso stampare la variabile di classe super ereditata i nella classe C tramite il metodo di visualizzazione e, naturalmente, la variabile che ho definito nella classe C stessa. La domanda è come stampare il terzo i che ha il valore "20".

So che posso definire un metodo nella classe B che restituisce super.i; e chiamiamolo attraverso il suo oggetto in classe A che stamperà la terza variabile io e ho anche saputo che posso creare un oggetto di classe A, ma c'è un altro modo usando super o qualsiasi altra cosa per accedere direttamente alla terza variabile in la classe C.

Anche l'output è:

      I am in constructor of the parent class
      I am in constructor of the subclass
      I am in constructor of the main class
      40
      30
  1. perché, come questa parola chiave, la parola chiave super non può essere utilizzata all'interno dei metodi statici?

  2. perché il costruttore di super classi ha chiamato per inizializzare le variabili ereditate di una sottoclasse? Questo non ha senso perché se una classe estende un'altra classe, le variabili e i metodi saranno come se fossero stati dichiarati localmente nella classe in altre parole i suoi membri. Quindi, perché il costruttore della sottoclasse non può inizializzare quei membri ereditati e deve chiamare il costruttore super-classe per inizializzarli.

posta With A SpiRIT 01.12.2015 - 04:24
fonte

3 risposte

3

Oltre a quanto sopra, considera il seguente scenario:

  • Inizi con queste due classi.

     class A {
        int i = 20;
    
        A() {
            System.out.println("I am in constructor of the parent class");
        }
    }
    
    class B extends A {
        int i = 30;
    
        B() {
            System.out.println("I am in constructor of the subclass");
        }
    }
    
  • Compilate entrambe le classi, crea due file di classe: A.class e B.class

  • Ora cambi idea e riscrivi A:

     class A {
        int i = 10;
    
        A() {
            System.out.println("I am in constructor of the parent class");
        }
    }
    
  • Ricompila A, quindi ottieni un nuovo A.class , che sostituisci il vecchio A.class con

Ora la domanda è: in che modo B sa che il codice di inizializzazione A s è cambiato? Non hai ricompilato B , né dovresti essere obbligato a farlo. Dopotutto, B potrebbe già essere impacchettato in un altro barattolo, forse anche in un prodotto diverso su cui non hai alcun controllo. *

L'unico modo ragionevole per supportare questo caso è che il costruttore di B s inizi a chiamare A s costruttore e lasci che A si inizializzi da solo.

* Questo può sembrare inverosimile all'inizio, ma questo è esattamente ciò che accade quando vengono modificati i dettagli di implementazione interna delle classi JDK. Tutte le applicazioni Java compilate in precedenza nel mondo dovrebbero funzionare perfettamente con il nuovo JDK.

    
risposta data 01.12.2015 - 16:14
fonte
4

Molto di questo è spiegato nella sezione JLS 15.11 :

15.11.2 Accessing Superclass Members using super
The form super.Identifier refers to the field named Identifier of the current object, but with the current object viewed as an instance of the superclass of the current class.

La parola chiave contiene dell'oggetto corrente . Se non esiste alcun oggetto corrente, come nel caso di un metodo statico, non puoi utilizzare il metodo super.

Quando si tratta del costruttore, la super classe è responsabile dell'inizializzazione dei suoi campi. Questo è necessario perché potrebbero esserci campi privati all'interno della super classe a cui una sottoclasse non ha accesso.

Inoltre, richiedere alla sottoclasse di istanziare lo stato della super classe può richiedere alla sottoclasse di avere più informazioni del necessario e richiede anche un accoppiamento più stretto tra la superclasse e la sottoclasse di quanto sia desiderabile - qualsiasi modifica ai campi nella superclasse richiederebbe un cambiamento in tutte le sottoclassi. Questa è una brutta cosa.

Quindi, previeni questo fatto negativo facendo in modo che la sottoclasse chiami il costruttore della superclasse quando viene creata.

    
risposta data 01.12.2015 - 04:52
fonte
1

Il tuo codice è incompleto - ecco cosa ha aggiunto Java per te:

class A extends Object { /* <-- Added */ 
    int i = 20;
    A() {
        super(); /* <-- Added */ 
        System.out.println("I am in constructor of the parent class");
    }
}

E le tue altre classi fanno lo stesso.

Tutte le classi estendono qualche altra classe, anche se è "solo" Oggetto .

"super" si riferisce alla super-classe dell'istanza corrente ma i metodi statici hanno nessuna istanza; sono solo blocchi di codice "allegati" a una classe, ma non fanno riferimento a nessun dato contenuto nell'istanza stessa. Se questa fosse una domanda .Net, ti indicherei i metodi Split () e Join () sulla classe String; il metodo Split [istanza] spezza il valore corrente contenuto nell'oggetto String ma il metodo [statico] Join accetta sia il delimitatore che il valore [array] come argomenti e li unisce.

I costruttori sono intrinsecamente privati nella loro azione. Il loro compito è preparare l'oggetto stesso per andare al lavoro, senza alcun riferimento alla sua super classe o qualsiasi sottoclasse (di cui non dovrebbe sapere nulla). L'istanziazione percorre tutta la "catena" di super-classe, fino a Object, ed esegue il costruttore su ogni classe nel modo "back down".

    
risposta data 01.12.2015 - 13:27
fonte

Leggi altre domande sui tag