Dubbio su super.ATTRIBUTo- java

di il
9 risposte

Dubbio su super.ATTRIBUTo- java

Buonsalve, credevo di aver superato lo step di "principiante" , ma sono incappato in un comportamento che non riesco a spiegarmi .
class Vettura{
	//ATTRIBUTI
	String s="subaru";

}



class Auto extends Vettura{
	
//	String s=" panda";
	  //costruttore()
	Auto()
        {
	s="panda";
	}


	//metodo
	public void Accendi()
	{
	  System.out.println(super.s);//mi stampa "panda"
	  
	}

}

public class prova{
 public static void main(String[] args)
 {
	//istanzio oggetto
	Auto a=new Auto();
	
	a.Accendi();	
 }//end main
}//end class

Non riesco a capire come mai , nonostante stia cercando di accedere all'attributo della classePadre mediante l'utilizzo di super.ATTRIBUTO, mi stampa l'attributo s dell'istanza corrente.
Visto che l'attributo s lo vado a sovrascrivere SOLO per un oggetto della CLASSE Figlio , con super.ATTRIBUTO non dovrei accedere alla sua ""versione originale"" (ovvero s="subaru" della CLASSE PADRE) ?

Non ne riesco proprio a venire a capo

L'unica spiegazione plausibile sarebbe che : laddove lavoro con degli Attributi ereditati , in realtà la jvm si va a fare implicitamente una super.s
ovvero in quel costruttore() della CLASSE FIGLIA quel che in realtà avviene è :
//costruttore()
	Auto()
        {
	super.s="panda";
	}
Ma non ne sono sicuro.
Attendo conferma

9 Risposte

  • Re: Dubbio su super.ATTRIBUTo- java

    L'espressione super.s fa sempre riferimento al s della superclasse .. non è questo il punto.
    Il punto è che hai "commentato" (=rimosso) la variabile s di Auto, quindi il costruttore di Auto va ad assegnare alla s di Vettura che è ereditata.
  • Re: Dubbio su super.ATTRIBUTo- java

    Premessa: grazie per la risposta

    Il "commentato" è voluto .
    il costruttore di Auto va ad assegnare alla s di Vettura che è ereditata
    Il costruttore di Auto non dovrebbe inizializzarmi solo quella che è "la variabile locale s " dell'istanza di Auto su cui sto invocando il metodo: Accendi() ?
    La variabile s della ClassePadre dovrebbe restare immutata , no?
  • Re: Dubbio su super.ATTRIBUTo- java

    La variabile s di Auto non esiste proprio in memoria, perché l'hai commentata. C'è solo s di Vettura. Che deve fare il povero costruttore?
  • Re: Dubbio su super.ATTRIBUTo- java

    pepp1995 ha scritto:


    il costruttore di Auto va ad assegnare alla s di Vettura che è ereditata
    Il costruttore di Auto non dovrebbe inizializzarmi solo quella che è "la variabile locale s " dell'istanza di Auto su cui sto invocando il metodo: Accendi() ?
    La variabile s della ClassePadre dovrebbe restare immutata , no?
    Se lo scenario è il seguente:
    class Vettura {
        String s="subaru";
    }
    
    class Auto extends Vettura {
        String s=" panda";
    
        Auto() {
            s="panda";
        }
    
        // .......
    }
    Quando crei un oggetto Auto, l'oggetto contiene 2 variabili che nel sorgente si chiamano (guarda caso) entrambe "s". Ma sono variabili DISTINTE e potrebbero evolvere, come valore, in maniera completamente differente.
    La variabile "s" di Auto semplicemente nasconde la variabile "s" di Vettura, tecnicamente si chiama hiding (attenzione, non shadowing che è un'altra cosa).
    Quindi all'interno di Auto: solo "s" (o esplicitamente "this.s") fa riferimento alla variabile di Auto mentre "super.s" fa riferimento alla variabile di Vettura.

    Se invece lo scenario è il seguente:
    class Vettura {
        String s="subaru";
    }
    
    class Auto extends Vettura {     // Auto NON ha una variabile "s"
        Auto() {
            s="panda";
        }
    
        // .......
    }
    Allora quando crei un oggetto Auto, c'è una sola variabile chiamata "s". La variabile s di Vettura non è privatepackage level) e le due classi sono nello stesso package, quindi Auto "eredita" la variabile s da Vettura, a cui può accedere. Ereditare il membro da Vettura è come se il membro fosse proprio definito in Auto (anche se lessicalmente non lo è).

    Quindi all'interno di Auto: in questo caso "s" oppure "super.s" è indifferente, fanno sostanzialmente la stessa cosa, ovvero fanno riferimento all'unica variabile s di Vettura.

    Tutto qui.
  • Re: Dubbio su super.ATTRIBUTo- java

    Ereditare il membro da Vettura è come se il membro fosse proprio definito in Auto (anche se lessicalmente non lo è).
    La spiegazione non mi torna.
    Se fosse definita in Auto , io potrei fare semplicemente
    s="panda"
    al di fuori del costruttore , ovvero fare:
    class Auto extends Vettura{
    s="panda";

    //metodo
    public void Accendi()
    {
    System.out.println(super.s);//mi stampa "panda"

    }

    }
    Ma non è così perché ho un errore a tempo di compilazione.

    Questo mi porta a pensare che una "variabile ereditata" non è ereditata ""dalla CLASSE in sé "" bensì "da tutte le ISTANZE di quella CLASSE""

    in questo caso "s" oppure "super.s" è indifferente, fanno sostanzialmente la stessa cosa, ovvero fanno riferimento all'unica variabile s di Vettura
    Ma quindi "super.s" non è equivalente a "1.Dichiarare static quel membro della classe Padre e poi 2.fare Vettura.s" ?

    E se è così , "super" la posso vedere come "una reference di Tipo Padre che punta ad un oggetto di Tipo Figlio" (UPCASTING) ??
    Nello specifico :
    -fare
    System.out.println(super.s);
    è la stessa cosa che fare
    Vettura a=new Auto();
    System.out.println(a.s);
    ?
  • Re: Dubbio su super.ATTRIBUTo- java

    pepp1995 ha scritto:


    Se fosse definita in Auto , io potrei fare semplicemente
    s="panda"
    al di fuori del costruttore , ovvero fare:
    Ma non è così perché ho un errore a tempo di compilazione.
    No, non puoi. Non si possono mettere istruzioni fuori da metodi/costruttori/initialization block!

    Insomma, una istruzione

    s=".....";

    NON la puoi mettere così da sola fuori da metodi/costruttori.

    Puoi mettere un System.out.println( ...); fuori da metodi/costruttori? NO
    Puoi mettere if, switch ecc.... fuori da metodi/costruttori? NO

    E' una questione di sintassi, non c'entra l'ereditarietà!

    pepp1995 ha scritto:


    Questo mi porta a pensare che una "variabile ereditata" non è ereditata ""dalla CLASSE in sé "" bensì "da tutte le ISTANZE di quella CLASSE""
    "Ereditare" in Java è più che altro una questione di visibilità/accessibilità di un membro.

    Se la situazione fosse (nota i private !):
    class Vettura {
        private String s="subaru";
    }
    
    class Auto extends Vettura {
        private String s=" panda";
    
        Auto() {
            s="panda";
        }
    
        // .......
    }
    Un oggetto Auto COMUNQUE possiede DUE variabili. Semplicemente sono private, quindi:
    a) Auto non può ereditare "s" da Vettura
    b) In Auto "super.s" non sarebbe fattibile dato che per Auto "non esiste" la s di Vettura (non la vede proprio ...)

    Ma nell'oggetto c'è effettivamente lo spazio per DUE variabili che sono distinte e potrebbero avere valori differenti.

    pepp1995 ha scritto:


    Ma quindi "super.s" non è equivalente a "1.Dichiarare static quel membro della classe Padre e poi 2.fare Vettura.s" ?
    Lo static qui non c'entra niente. static vuol solo dire che il membro "appartiene" alla classe e non a ciascun distinto oggetto.

    Se in Vettura s fosse static, vuol solo dire che s di Vettura è "globale" e non sta in ciascun oggetto Auto ma il resto non cambierebbe.
    Auto lo può "vedere" (se non private e accessibile).

    pepp1995 ha scritto:


    E se è così , "super" la posso vedere come "una reference di Tipo Padre che punta ad un oggetto di Tipo Figlio" (UPCASTING) ??
    Nello specifico :
    -fare
    System.out.println(super.s);
    è la stessa cosa che fare
    Vettura a=new Auto();
    System.out.println(a.s);
    ?
    Se hai un reference v di tipo Vettura, allora v.s è appunto il riferimento al s di Vettura.


    EDIT: ecco più completo:
    public class Prova {
        public static void main(String[] args) {
            Vettura v = new Auto();
            System.out.println(v.s);             // stampa vettura
            System.out.println(((Auto)v).s);     // stampa auto
    
            Auto a = new Auto();
            System.out.println(a.s);             // stampa auto
            System.out.println(((Vettura)a).s);  // stampa vettura
        }
    }
    
    class Vettura {
        String s = "vettura";
    }
    
    class Auto extends Vettura {
        String s = "auto";
    }
  • Re: Dubbio su super.ATTRIBUTo- java

    Un oggetto Auto COMUNQUE possiede DUE variabili. Semplicemente sono private, quindi:
    a) Auto non può ereditare "s" da Vettura
    b) In Auto "super.s" non sarebbe fattibile dato che per Auto "non esiste" la s di Vettura (non la vede proprio ...)
    Ok, su questo caso particolare sono d'accordo.
    Ma se ci focalizziamo su super, la posso vedere come una "reference all'oggetto su cui invochiamo il metodo in cui stiamo utilizzando quella key-word "?

    Perché se fosse così , allora super.s mi permetterebbe di accedere alla "variabile s di quell'oggetto" e questo spiegherebbe il perché mi stampa "panda"

    Ed il risultato sarebbe che: in assenza di HIDING di una variabile--> "super.s" è equivalente a "this.s"

    POI e SOLO POI , nel caso "eclatante" , per cui faccio l'hiding della variabile s della Classe Padre
    "DICHIARANDO ed INIZIALIZZANDO una variabile di stesso nome nella CLASSE FIGLIO" -->
    tra le due variabili dell'oggetto , mi si sceglie quella "originale".

    Ma il discorso avrebbe senso se "super" è vista come una "reference ad un oggetto" e non come una "reference ad una CLASSE"

    In pratica: il problema non è tanto su "cosa fa super.Attributo" , ma "chi è super"
  • Re: Dubbio su super.ATTRIBUTo- java

    pepp1995 ha scritto:


    ma "chi è super"
    Dal JLS (§15.11.2): 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.


    Se avessi:
    class Vettura {
        String s = "vettura";
    }
    
    class Auto extends Vettura {
        // niente
    }
    
    class Ferrari extends Auto {
        String s = "ferrari";
    
        public void prova() {
            System.out.println(this.s);          // ferrari (ovvio)
            System.out.println(super.s);         // vettura
            System.out.println(((Auto)this).s);  // vettura
        }
    }
    Auto NON definisce una variabile di istanza "s". MA la "eredita" da Vettura.
    Quindi in Ferrari, super.s vuol dire: "guarda la s in Auto" e Auto concettualmente è come se avesse la variabile s di Vettura perché la eredita!!!
  • Re: Dubbio su super.ATTRIBUTo- java

    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.
    Chiaro , è comunque una reference all' oggetto corrente, MA visto come se fosse un istanza della superclasse.

    Dunque super.s mi accede comunque alla variabile s dell'oggetto corrente , che poiché non è stata "nascosta" da una variabile di stesso nome dichiarata nella classe Figlia --> è la variabile della ClassePadre

    Grazie mille
Devi accedere o registrarti per scrivere nel forum
9 risposte