Upcasting e Downcasting
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 30 de 87.
Na lição anterior, você viu como uma variável do tipo pai pode conter um objeto filho: Animal myPet = new Dog(). Essa atribuição é chamada de upcasting e acontece automaticamente porque um Dog é sempre um Animal.
Upcasting sobe na hierarquia de herança. É implícito e sempre seguro:
Dog dog = new Dog();
Animal animal = dog; // Upcasting - automáticoAo fazer upcasting, você só pode acessar métodos definidos na classe pai. Os métodos específicos da classe filha ficam ocultos, embora o objeto ainda seja um Dog internamente.
Downcasting segue na direção oposta, convertendo uma referência ao tipo pai de volta para um tipo filho. Isso exige uma conversão explícita porque nem sempre é seguro:
Animal animal = new Dog(); // Upcasting
Dog dog = (Dog) animal; // Downcasting - cast explícito necessário
dog.bark(); // Agora podemos acessar os métodos de DogFazer downcasting é arriscado. Se o objeto não for realmente do tipo para o qual você está convertendo, o Java lançará uma ClassCastException em tempo de execução:
Animal animal = new Cat();
Dog dog = (Dog) animal; // Compila, mas falha em tempo de execução!O compilador não consegue detectar esse erro porque ele vê apenas os tipos declarados. O tipo real do objeto só é conhecido quando o programa é executado. Na próxima lição, você aprenderá a verificar com segurança o tipo de um objeto antes de fazer o downcast.
Desafio
FácilVamos criar um sistema de reprodução de mídia que demonstra tanto upcasting quanto downcasting na prática. Você criará uma hierarquia de tipos de mídia e praticará a conversão entre referências de pai e de filho.
Você organizará seu código em quatro arquivos:
Media.java: Crie a classe base compartilhada por todos os tipos de mídia. Cada item de mídia possui um campotitle(String). Inclua um construtor para inicializá-lo, um método gettergetTitle()e um métodoplay()que imprime:Playing: [title]Song.java: Crie uma classe que estenda Media. As músicas possuem um campo adicionalartist(String). Usesuperpara a inicialização da classe pai. Substituaplay()para imprimir:Playing song: [title] by [artist]. Adicione um métodoshowArtist()que imprime:Artist: [artist]Podcast.java: Crie outra classe que estenda Media. Os podcasts possuem um campoepisode(int). Substituaplay()para imprimir:Playing podcast: [title] - Episode [episode]. Adicione um métodoshowEpisode()que imprime:Episode: [episode]Main.java: Demonstre upcasting e downcasting com seus tipos de mídia. Você receberá quatro entradas: o título de uma música, o nome de um artista, o título de um podcast e um número de episódio.Primeiro, crie um Song e faça o upcasting para uma referência Media. Chame
play()nessa referência para observar o polimorfismo em tempo de execução.Em seguida, faça o downcasting dessa referência Media de volta para Song e chame
showArtist()para acessar o método específico da classe filha.Depois, crie um Podcast e faça o upcasting para uma referência Media. Chame
play()nessa referência.Por fim, faça o downcasting dessa referência Media de volta para Podcast e chame
showEpisode().
Você receberá quatro entradas: o título da música (String), o nome do artista (String), o título do podcast (String) e o número do episódio (int).
Sua saída deve mostrar quatro linhas — duas para a música (a saída de reprodução e as informações do artista) e duas para o podcast (a saída de reprodução e as informações do episódio). Observe como o upcasting permite tratar diferentes tipos de mídia de maneira uniforme, enquanto o downcasting permite acessar seus recursos exclusivos!
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler entradas
String songTitle = scanner.nextLine();
String artistName = scanner.nextLine();
String podcastTitle = scanner.nextLine();
int episodeNumber = scanner.nextInt();
// TODO: Crie um Song e faça upcast para uma referência Media
// TODO: Chame play() na referência Media (demonstra polimorfismo)
// TODO: Faça downcast da referência Media de volta para Song
// TODO: Chame showArtist() na referência Song
// TODO: Crie um Podcast e faça upcast para uma referência Media
// TODO: Chame play() na referência Media
// TODO: Faça downcast da referência Media de volta para Podcast
// TODO: Chame showEpisode() na referência Podcast
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão IteratorPratique por conta própria: Compilador de Java online