Menu
Coddy logo textTech

Upcasting y Downcasting

Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 30 de 87.

En la lección anterior, viste cómo una variable de tipo padre puede contener un objeto hijo: Animal myPet = new Dog(). Esta asignación se llama upcasting, y ocurre automáticamente porque un Dog siempre es un Animal.

Upcasting se mueve hacia arriba en la jerarquía de herencia. Es implícito y siempre seguro:

Dog dog = new Dog();
Animal animal = dog;  // Upcasting - automático

Cuando realizas un upcast, solo puedes acceder a los métodos definidos en la clase padre. Los métodos específicos de la clase hija se ocultan, aunque el objeto siga siendo un Dog internamente.

Downcasting va en la dirección opuesta, convirtiendo una referencia de padre de nuevo a un tipo hijo. Esto requiere una conversión explícita (cast) porque no siempre es seguro:

Animal animal = new Dog();  // Upcasting
Dog dog = (Dog) animal;     // Downcasting - se requiere conversión explícita
dog.bark();                 // Ahora podemos acceder a los métodos de Dog

El downcasting es arriesgado. Si el objeto no es realmente del tipo al que se está realizando el casting, Java lanza una ClassCastException en tiempo de ejecución:

Animal animal = new Cat();
Dog dog = (Dog) animal;  // ¡Compila, pero falla en tiempo de ejecución!

El compilador no puede detectar este error porque solo ve los tipos declarados. El tipo de objeto real solo se conoce cuando el programa se ejecuta. En la próxima lección, aprenderás cómo verificar de forma segura el tipo de un objeto antes de realizar un downcasting.

challenge icon

Desafío

Fácil

Construyamos un sistema de reproductor de medios que demuestre tanto el upcasting como el downcasting en acción. Crearás una jerarquía de tipos de medios y practicarás la conversión entre referencias de padre e hijo.

Organizarás tu código en cuatro archivos:

  • Media.java: Crea la clase base que comparten todos los tipos de medios. Cada elemento de medio tiene un campo title (String). Incluye un constructor para inicializarlo, un método getter getTitle() y un método play() que imprima: "Playing: " + title
  • Song.java: Crea una clase que extienda de Media. Las canciones tienen un campo adicional artist (String). Usa super para la inicialización del padre. Sobrescribe play() para imprimir: "Playing song: " + title + " by " + artist. Añade un método showArtist() que imprima: "Artist: " + artist
  • Podcast.java: Crea otra clase que extienda de Media. Los podcasts tienen un campo episode (int). Sobrescribe play() para imprimir: "Playing podcast: " + title + " - Episode " + episode. Añade un método showEpisode() que imprima: "Episode: " + episode
  • Main.java: Demuestra el upcasting y downcasting con tus tipos de medios. Recibirás cuatro entradas: un título de canción, un nombre de artista, un título de podcast y un número de episodio.

    Primero, crea un Song y realiza un upcast a una referencia de Media. Llama a play() en esta referencia para ver el polimorfismo en tiempo de ejecución en acción.

    Luego, realiza un downcast de esa referencia de Media de vuelta a un Song y llama a showArtist() para acceder al método específico del hijo.

    Después, crea un Podcast y realiza un upcast a una referencia de Media. Llama a play() en esta referencia.

    Finalmente, realiza un downcast de esa referencia de Media de vuelta a un Podcast y llama a showEpisode().

Recibirás cuatro entradas: el título de la canción (String), el nombre del artista (String), el título del podcast (String) y el número de episodio (int).

Tu salida debería mostrar cuatro líneas: dos para la canción (su salida de reproducción y la información del artista) y dos para el podcast (su salida de reproducción y la información del episodio). ¡Observa cómo el upcasting te permite tratar diferentes tipos de medios de manera uniforme, mientras que el downcasting te permite acceder a sus características únicas!

Hoja de referencia

En Java, el upcasting (conversión ascendente) sube en la jerarquía de herencia y ocurre automáticamente. Un objeto hijo puede ser asignado a una variable de tipo padre:

Dog dog = new Dog();
Animal animal = dog;  // Upcasting - automático

Cuando realizas un upcasting, solo puedes acceder a los métodos definidos en la clase padre, aunque el objeto siga siendo del tipo hijo internamente.

Downcasting (conversión descendente) convierte una referencia de padre de vuelta a un tipo hijo. Requiere un cast explícito:

Animal animal = new Dog();  // Upcasting
Dog dog = (Dog) animal;     // Downcasting - se requiere un cast explícito
dog.bark();                 // Ahora podemos acceder a los métodos de Dog

El downcasting es arriesgado. Si el objeto no es realmente del tipo al que estás realizando el cast, Java lanza una ClassCastException en tiempo de ejecución:

Animal animal = new Cat();
Dog dog = (Dog) animal;  // ¡Compila, pero falla en tiempo de ejecución!

El compilador no puede detectar este error porque solo ve los tipos declarados. El tipo de objeto real solo se conoce cuando el programa se ejecuta.

Pruébalo tú mismo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Leer entradas
        String songTitle = scanner.nextLine();
        String artistName = scanner.nextLine();
        String podcastTitle = scanner.nextLine();
        int episodeNumber = scanner.nextInt();
        
        // TODO: Crear una Song (Canción) y realizar un upcast a una referencia de Media
        
        // TODO: Llamar a play() en la referencia de Media (demuestra polimorfismo)
        
        // TODO: Realizar un downcast de la referencia de Media de vuelta a Song
        
        // TODO: Llamar a showArtist() en la referencia de Song
        
        // TODO: Crear un Podcast y realizar un upcast a una referencia de Media
        
        // TODO: Llamar a play() en la referencia de Media
        
        // TODO: Realizar un downcast de la referencia de Media de vuelta a Podcast
        
        // TODO: Llamar a showEpisode() en la referencia de Podcast
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos