Visualizzazione dei risultati da 1 a 5 su 5
  1. #1

    [Primi passi con Java]

    Ciao ragazzi,
    ho appena iniziato a studiare il java. A tal proposito, mi sto cimentando con il polimorfismo. Per prova ho scritto queste classi:

    codice:
    public class Animale {
      
       public void interroga(){
    	   	   System.out.println("Ciao");
       }
    }
    
    
    public class Cane extends Animale{
    	 
    	 public void interroga(){
    		   
    		   System.out.println("Bau");
    	   }
    
    }
    
    public class Gatto extends Animale{
    	
    	 public void interroga(){
    		   
    		   System.out.println("Miao");
    	   }
    
    }
    
    
    
    public class Chiama {
    	
    	 public static void chiama(Animale a){
    		   a.interroga();
    	   }
      public static void main(String[] args){
    	  Animale a= new Cane();
    	  Cane b = new Cane();
    	  Gatto c = new Gatto();
    	  chiama(a);
    	  
      }
    }
    Allora, la cosa che non capisco è questa. con l'istruzione Animale a= new Cane() io creo un oggetto di tipo Cane e lo memorizzo in un oggetto di tipo animale. Quindi dovrei fare il cosiddetto upcasting. Quindi, siccome a è di tipo Animale, dovrebbe richiamare il metodo interroga della classe Animale. Ma in realtà a chiama interroga della classe Cane, stampando a video "Bau",ma perchè?

    Allora che differenza c'è con lo scrivere Cane a = new Cane()? Questa cosa davvero non riesco a capirla. Io pensavo che facendo l'upcasting, si perdesse tutte le implementazioni fatte nella classe figlia. Ma in realtà non si perdono.

    Altra cosa che non ho capito è l'incapsulamento. Cioè, cosa cambia se alle variabili di una classe non ci accedo direttamente ma mediante dei metodi getters e setters? Mi fareste un breve esempio in cui è pericoloso non usare l'incapsulamento? Grazie

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,472

    Re: [Primi passi con Java]

    Originariamente inviato da sigfrid_xxxx
    Allora, la cosa che non capisco è questa. con l'istruzione Animale a= new Cane() io creo un oggetto di tipo Cane e lo memorizzo in un oggetto di tipo animale. Quindi dovrei fare il cosiddetto upcasting. Quindi, siccome a è di tipo Animale, dovrebbe richiamare il metodo interroga della classe Animale. Ma in realtà a chiama interroga della classe Cane, stampando a video "Bau",ma perchè?
    Ciò che non riesci a comprendere è esattamente l'effetto del polimorfismo.

    Tu hai una variabile di tipo Animale che, potenzialmente, può riferirsi ad istanze della classe Animale stessa o di classi discendenti; tuttavia, benché il riferimento sia di tipo Animale, l'oggetto vero e proprio appartiene alla classe Cane, ed è proprio per questo motivo che Java segue l'implementazione del metodo invocato di questa classe.

    A runtime, quando il metodo viene invocato, il tipo di oggetto con cui si ha a che fare viene verificato; trattandosi di un oggetto di tipo Cane, è l'implementazione di questa classe ad essere invocata.

    Questo consente di memorizzare nel riferimento qualsiasi oggetto sia di tipo Animale o appartenente ad una classe discendente e, invocando un metodo, ottenere l'esecuzione dell'implementazione specifica fornita dalla classe di appartenenza.

    Originariamente inviato da sigfrid_xxxx
    Allora che differenza c'è con lo scrivere Cane a = new Cane()? Questa cosa davvero non riesco a capirla. Io pensavo che facendo l'upcasting, si perdesse tutte le implementazioni fatte nella classe figlia. Ma in realtà non si perdono.
    Avere una variabile o un parametro che appartiene alla classe base significa poter passare a quell'identificatore un riferimento ad un oggetto che appartiene a tale classe o a una delle sue discendenti, indifferentemente. Ma nel caso di metodi non "chiusi", ciascuna classe può ridefinire il loro comportamento per personalizzarlo.

    Forse questa lezione può essere più chiara ed illustrativa.

    Originariamente inviato da sigfrid_xxxx
    Altra cosa che non ho capito è l'incapsulamento. Cioè, cosa cambia se alle variabili di una classe non ci accedo direttamente ma mediante dei metodi getters e setters? Mi fareste un breve esempio in cui è pericoloso non usare l'incapsulamento? Grazie
    Supponi di avere una classe che contiene i dati di una persona, inclusa l'età. Essa deve logicamente essere maggiore di zero; supponendo di memorizzarla in un campo intero e rendere quest'ultimo pubblico, qualsiasi oggetto faccia uso di un'istanza di questa classe, può accedere direttamente al campo e memorizzare un valore che potrebbe non essere valido, ad esempio -1. L'uso di metodi get e set consente di regolare l'accesso a questi campi, che rappresentano lo stato complessivo del tuo oggetto, e garantire che tale stato rimanga consistente, nel caso specifico impedendo all'oggetto "client" che utilizza l'istanza di memorizzare un valore negativo per l'età, inserendo il controllo della validità del valore da impostare nel metodo di set, generando un'eccezione in caso di errore oppure lasciando il valore precedentemente memorizzato.

    Un altro uso dei metodi getter e setter è la possibilità di generare effetti collaterali; ad esempio, un controllo visuale potrebbe disporre di un metodo setBackground che imposta il valore di un campo privato memorizzando il colore passato come parametro al metodo di set e, inoltre, provocare il ridisegno del controllo sullo schermo (poiché il colore di sfondo è cambiato).

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3

    Re: Re: [Primi passi con Java]

    Originariamente inviato da alka


    A runtime, quando il metodo viene invocato, il tipo di oggetto con cui si ha a che fare viene verificato; trattandosi di un oggetto di tipo Cane, è l'implementazione di questa classe ad essere invocata.

    Questo consente di memorizzare nel riferimento qualsiasi oggetto sia di tipo Animale o appartenente ad una classe discendente e, invocando un metodo, ottenere l'esecuzione dell'implementazione specifica fornita dalla classe di appartenenza.
    Ma quindi il cast verso l'alto è del puntatore all'oggetto, non dell'oggetto vero e proprio. Voglio dire, se mi dicono che faccio un upcasting, io intendo che l'oggetto Cane diventa Animale, quindi essendo Animale, perdo le implementazioni definite nella classe Cane. In alcune guide è scritto che facendo upcasting si perdono caratteristiche definite nella classe derivata..




    L'uso di metodi get e set consente di regolare l'accesso a questi campi, che rappresentano lo stato complessivo del tuo oggetto, e garantire che tale stato rimanga consistente, nel caso specifico impedendo all'oggetto "client" che utilizza l'istanza di memorizzare un valore negativo per l'età, inserendo il controllo della validità del valore da impostare nel metodo di set, generando un'eccezione in caso di errore oppure lasciando il valore precedentemente memorizzato.
    Ma questo controllo non si può fare anche senza tali metodi? Magari in maniera meno diretta, ma non vedo perchè non possa controllare un valore senza usare metodi get e set

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,472
    Originariamente inviato da sigfrid_xxxx
    Ma quindi il cast verso l'alto è del puntatore all'oggetto, non dell'oggetto vero e proprio. Voglio dire, se mi dicono che faccio un upcasting, io intendo che l'oggetto Cane diventa Animale, quindi essendo Animale, perdo le implementazioni definite nella classe Cane. In alcune guide è scritto che facendo upcasting si perdono caratteristiche definite nella classe derivata..
    Ciò a cui si riferiscono le guide è un altro concetto.

    Ad una variabile di tipo Animale puoi assegnare un riferimento ad un oggetto Cane e Gatto; perdere le caratteristiche definite nella classe derivata significa che, trattandosi di una variabile di tipo Animale, non puoi accedere specificatamente ai membri che esistono solamente in Cane o Gatto proprio perché le istanze di entrambe queste classi potrebbero essere assegnate alla variabile, quindi non è possibile fare uso dei metodi specifici dell'una e dell'altra, ma solo dei metodi in comune alle due classi, cioè quelli introdotti nella classe base da cui entrambe derivano.

    Originariamente inviato da sigfrid_xxxx
    Ma questo controllo non si può fare anche senza tali metodi? Magari in maniera meno diretta, ma non vedo perchè non possa controllare un valore senza usare metodi get e set
    E come potresti farlo? Il controllo della validità di un campo è sotto la responsabilità dell'oggetto stesso, e non dell'oggetto che lo utilizza e che, per errori di programmazione o altri motivi, potrebbe omettere quest'azione "rompendo" di fatto l'oggetto, cioè portandolo ad uno stato incongruente.

    L'accesso ai dati che costituiscono lo stato del componente devono essere protetti rendendoli privati e, attraverso i metodi getter/setter, è necessario garantire che qualsiasi dato venga impostato, invocando i suddetti metodi, sia valido e porti l'oggetto da uno stato A ad uno stato B, entrambi consistenti.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    Originariamente inviato da alka
    Ad una variabile di tipo Animale puoi assegnare un riferimento ad un oggetto Cane e Gatto; perdere le caratteristiche definite nella classe derivata significa che, trattandosi di una variabile di tipo Animale, non puoi accedere specificatamente ai membri che esistono solamente in Cane o Gatto proprio perché le istanze di entrambe queste classi potrebbero essere assegnate alla variabile, quindi non è possibile fare uso dei metodi specifici dell'una e dell'altra, ma solo dei metodi in comune alle due classi, cioè quelli introdotti nella classe base da cui entrambe derivano.
    Ma quindi se ho un metodo che prende in ingresso un oggetto di tipo animale, supponiamo metodo(Animale a),
    poi scrivo,
    Animale b = new Cane();
    Cane c = new Cane();

    poi ,

    metodo(b);

    metodo(c);

    Cosa cambia in questo caso? In quale caso devo seguire la prima strada e in quale la seconda? Grazie.

    [/QUOTE]

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.