Menu
Coddy logo textTech

Upcasting e Downcasting

Parte da seção Programação Orientada a Objetos do Journey de C# da Coddy. Lição 29 de 70.

Ao trabalhar com hierarquias de herança, muitas vezes você precisa converter entre tipos base e derivados. O upcasting converte um tipo derivado em seu tipo base, enquanto o downcasting faz o oposto.

A conversão para uma classe base é implícita e sempre segura, pois é garantido que uma classe derivada tenha tudo o que a classe base tem:

Dog myDog = new Dog();
Animal animal = myDog;  // Upcasting - implícito, sempre funciona

O downcasting exige uma conversão explícita e pode falhar em tempo de execução se o objeto não for realmente do tipo para o qual você está fazendo a conversão:

Animal animal = new Dog();
Dog dog = (Dog)animal;  // Downcasting - funciona porque é realmente um Dog

Animal cat = new Cat();
Dog wrong = (Dog)cat;   // Lança InvalidCastException!

Para fazer downcast com segurança, use a palavra-chave is para verificar o tipo primeiro ou use as, que retorna null em vez de lançar uma exceção:

if (animal is Dog d)
{
    d.Bark();  // Seguro - d só está disponível se a verificação passar
}

Dog maybeDog = animal as Dog;
if (maybeDog != null)
{
    maybeDog.Bark();
}

A abordagem de correspondência de padrões is é preferida no C# moderno porque combina a verificação de tipo e a conversão (cast) em uma única etapa, tornando seu código mais seguro e limpo.

challenge icon

Desafio

Fácil

Vamos criar um sistema de inspeção de veículos que demonstra como o upcasting e o downcasting permitem trabalhar de forma flexível com objetos em uma hierarquia de herança. Você criará diferentes tipos de veículos e escreverá código que identifica e interage com segurança com tipos específicos de veículos.

Você organizará seu código em quatro arquivos:

  • Vehicle.cs: Defina uma classe base Vehicle no namespace Inspection. Todo veículo tem uma propriedade LicensePlate (string) definida por meio de um construtor. Inclua um método chamado GetBasicInfo() que retorna "Vehicle: {LicensePlate}".
  • Car.cs: Defina uma classe Car no namespace Inspection que herda de Vehicle. Os carros têm uma propriedade adicional NumberOfDoors (int). O construtor aceita tanto a placa quanto a quantidade de portas. Adicione um método chamado Honk() que retorna "{LicensePlate} honks: Beep beep!".
  • Motorcycle.cs: Defina uma classe Motorcycle no namespace Inspection que herda de Vehicle. As motocicletas têm uma propriedade HasSidecar (bool). O construtor aceita a placa e o status do sidecar. Adicione um método chamado Rev() que retorna "{LicensePlate} revs: Vroom!".
  • Program.cs: No seu arquivo principal, você criará veículos e praticará tanto upcasting quanto downcasting seguro. Crie um Car e uma Motorcycle usando valores de entrada e, em seguida, armazene ambos em um array de referências Vehicle (upcasting). Percorra o array e, para cada veículo, imprima suas informações básicas. Depois, use a palavra-chave is com correspondência de padrões para fazer o downcasting com segurança: se for um Car, chame Honk(); se for uma Motorcycle, chame Rev().

Você receberá quatro entradas:

  • Placa do carro
  • Quantidade de portas
  • Placa da motocicleta
  • Possui sidecar (true ou false)

Imprima a saída neste formato para cada veículo no array:

{GetBasicInfo() result}
{Honk() or Rev() result based on actual type}

Por exemplo, se as entradas forem ABC-123, 4, XYZ-789 e false, a saída deverá ser:

Vehicle: ABC-123
ABC-123 honks: Beep beep!
Vehicle: XYZ-789
XYZ-789 revs: Vroom!

Observe como todos os veículos são armazenados como referências Vehicle (upcasting), mas você pode descobrir com segurança seus tipos reais e acessar métodos específicos de cada tipo usando a sintaxe de correspondência de padrões is para fazer o downcasting!

Experimente você mesmo

using System;
using Inspection;

class Program
{
    public static void Main(string[] args)
    {
        // Ler as entradas
        string carPlate = Console.ReadLine();
        int numberOfDoors = Convert.ToInt32(Console.ReadLine());
        string motorcyclePlate = Console.ReadLine();
        bool hasSidecar = Convert.ToBoolean(Console.ReadLine());
        
        // TODO: Criar um objeto Car usando carPlate e numberOfDoors
        
        // TODO: Criar um objeto Motorcycle usando motorcyclePlate e hasSidecar
        
        // TODO: Criar um array de referências Vehicle contendo ambos os veículos (upcasting)
        
        // TODO: Percorrer o array e para cada veículo:
        //   - Imprimir o resultado de GetBasicInfo()
        //   - Usar a palavra-chave 'is' com pattern matching para fazer o downcast com segurança:
        //     - Se for um Car, chamar e imprimir Honk()
        //     - Se for um Motorcycle, chamar e imprimir Rev()
    }
}
quiz iconTeste seus conhecimentos

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

Pratique por conta própria: Compilador de C# online