Menu
Coddy logo textTech

Upcasting e downcasting

Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 30 di 87.

Nella lezione precedente, hai visto come una variabile di tipo genitore possa contenere un oggetto figlio: Animal myPet = new Dog(). Questa assegnazione è chiamata upcasting e avviene automaticamente perché un Dog è sempre un Animal.

Upcasting risale la gerarchia di ereditarietà. È implicito e sempre sicuro:

Dog dog = new Dog();
Animal animal = dog;  // Upcasting - automatico

Quando esegui l'upcasting, puoi accedere solo ai metodi definiti nella classe genitore. I metodi specifici della classe figlia diventano nascosti, anche se l'oggetto sottostante è ancora un Dog.

Downcasting procede nella direzione opposta, convertendo un riferimento al genitore di nuovo in un tipo figlio. Questo richiede un cast esplicito perché non è sempre sicuro:

Animal animal = new Dog();  // Upcasting
Dog dog = (Dog) animal;     // Downcasting - è necessario un cast esplicito
dog.bark();                 // Ora possiamo accedere ai metodi di Dog

Il downcasting è rischioso. Se l'oggetto non è effettivamente del tipo in cui lo stai convertendo, Java genera una ClassCastException in fase di esecuzione:

Animal animal = new Cat();
Dog dog = (Dog) animal;  // Si compila, ma va in errore durante l'esecuzione!

Il compilatore non può rilevare questo errore perché vede solo i tipi dichiarati. Il tipo effettivo dell'oggetto si conosce solo quando il programma viene eseguito. Nella prossima lezione imparerai a verificare in sicurezza il tipo di un oggetto prima di eseguire il downcasting.

challenge icon

Sfida

Facile

Costruiamo un sistema di riproduzione multimediale che dimostri in azione sia l'upcasting sia il downcasting. Creerai una gerarchia di tipi multimediali e farai pratica convertendo i riferimenti tra classi padre e figlie.

Organizzerai il codice in quattro file:

  • Media.java: crea la classe base condivisa da tutti i tipi multimediali. Ogni elemento multimediale ha un campo title (String). Includi un costruttore per inizializzarlo, un metodo getter getTitle() e un metodo play() che stampa: Playing: [title]
  • Song.java: crea una classe che estende Media. Le canzoni hanno un campo aggiuntivo artist (String). Usa super per inizializzare la classe padre. Sovrascrivi play() affinché stampi: Playing song: [title] by [artist]. Aggiungi un metodo showArtist() che stampa: Artist: [artist]
  • Podcast.java: crea un'altra classe che estende Media. I podcast hanno un campo episode (int). Sovrascrivi play() affinché stampi: Playing podcast: [title] - Episode [episode]. Aggiungi un metodo showEpisode() che stampa: Episode: [episode]
  • Main.java: dimostra l'upcasting e il downcasting con i tuoi tipi multimediali. Riceverai quattro input: il titolo di una canzone, il nome di un artista, il titolo di un podcast e il numero dell'episodio.

    Per prima cosa, crea un Song ed esegui l'upcasting a un riferimento Media. Chiama play() su questo riferimento per vedere in azione il polimorfismo in fase di esecuzione.

    Poi, esegui il downcasting di quel riferimento Media di nuovo a Song e chiama showArtist() per accedere al metodo specifico della classe figlia.

    Quindi, crea un Podcast ed esegui l'upcasting a un riferimento Media. Chiama play() su questo riferimento.

    Infine, esegui il downcasting di quel riferimento Media di nuovo a Podcast e chiama showEpisode().

Riceverai quattro input: il titolo della canzone (String), il nome dell'artista (String), il titolo del podcast (String) e il numero dell'episodio (int).

Il tuo output dovrebbe mostrare quattro righe: due per la canzone (il risultato di play e le informazioni sull'artista) e due per il podcast (il risultato di play e le informazioni sull'episodio). Nota come l'upcasting ti permette di trattare in modo uniforme diversi tipi multimediali, mentre il downcasting ti permette di accedere alle loro caratteristiche specifiche!

Provalo tu

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Leggi gli input
        String songTitle = scanner.nextLine();
        String artistName = scanner.nextLine();
        String podcastTitle = scanner.nextLine();
        int episodeNumber = scanner.nextInt();
        
        // TODO: Crea un Song ed esegui un upcast a un riferimento Media
        
        // TODO: Chiama play() sul riferimento Media (dimostra il polimorfismo)
        
        // TODO: Esegui un downcast del riferimento Media a Song
        
        // TODO: Chiama showArtist() sul riferimento Song
        
        // TODO: Crea un Podcast ed esegui un upcast a un riferimento Media
        
        // TODO: Chiama play() sul riferimento Media
        
        // TODO: Esegui un downcast del riferimento Media a Podcast
        
        // TODO: Chiama showEpisode() sul riferimento Podcast
    }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Java online