🎓 Aulas de Programação Orientada a Objetos

Universo DC - Aprenda POO com exemplos práticos

Objetivo da Aula

Entender o conceito de Polimorfismo e como objetos de diferentes classes podem ser tratados de forma uniforme.

Aula 05: Polimorfismo


Conceito de Polimorfismo

O que é Polimorfismo?

Polimorfismo significa "muitas formas". Em POO, permite que objetos de diferentes classes sejam tratados de forma uniforme através de uma classe base ou interface comum. Analogia: Imagine um controle remoto universal. Ele pode controlar TV, ar-condicionado, som - todos diferentes, mas todos respondem ao botão "ligar" de forma similar.

Tipos de Polimorfismo

  1. Polimorfismo de Sobrescrita (Override): Métodos sobrescritos em classes filhas
  2. Polimorfismo de Sobrecarga (Overload): Múltiplos métodos com mesmo nome, parâmetros diferentes
  3. Polimorfismo de Interface: Objetos diferentes implementando mesma interface

Polimorfismo com Classes Base

Exemplo: Lista de Personagens

// TÓPICO: Polimorfismo com Classe Base
// Podemos colocar objetos de classes diferentes em uma lista da classe base
List<Personagem> personagens = new List<Personagem>();

// Adicionando heróis e vilões (objetos diferentes)
personagens.Add(new Heroi("Batman", 85, "Liga da Justiça"));
personagens.Add(new Heroi("Superman", 100, "Liga da Justiça"));
personagens.Add(new Heroi("Flash", 90, "Liga da Justiça"));
personagens.Add(new Vilao("Coringa", 80, "Legião do Mal"));
personagens.Add(new Vilao("Lex Luthor", 75, "Legião do Mal"));
personagens.Add(new Vilao("Darkseid", 95, "Apokolips"));

// TÓPICO: Polimorfismo em Ação
// Cada objeto chama sua própria implementação do método
foreach (Personagem personagem in personagens)
{
    // Mesmo método, comportamentos diferentes!
    personagem.Apresentar();    // Cada um se apresenta de forma diferente
    personagem.UsarPoder();     // Cada um usa poder de forma diferente
    Console.WriteLine();
}
Saída Esperada:
Olá! Eu sou Batman, herói da Liga da Justiça, nível 85!
Batman usa seu poder para proteger os inocentes!

Olá! Eu sou Superman, herói da Liga da Justiça, nível 100!
Superman usa seu poder para proteger os inocentes!

Cuidado! Eu sou Coringa, vilão da Legião do Mal, nível 80!
Coringa usa seu poder para causar caos e destruição!

Polimorfismo com Interfaces

Exemplo: Lista de Voadores

// TÓPICO: Polimorfismo com Interface
// Objetos diferentes que implementam a mesma interface
List<IVoador> voadores = new List<IVoador>();

// Criando objetos diferentes que voam
Heroi superman = new Heroi("Superman", 100, "Liga da Justiça");
superman.AltitudeMaxima = 10000;

Heroi mulherMaravilha = new Heroi("Mulher Maravilha", 95, "Liga da Justiça");
mulherMaravilha.AltitudeMaxima = 5000;

// Adicionando à lista (tratados como IVoador)
voadores.Add(superman);
voadores.Add(mulherMaravilha);

// TÓPICO: Polimorfismo através da Interface
// Todos voam, mas cada um pode ter implementação diferente
foreach (IVoador voador in voadores)
{
    voador.Voar();      // Cada um voa de sua forma
    voador.Pousar();    // Cada um pousa de sua forma
    Console.WriteLine();
}

Polimorfismo: Métodos Virtuais vs Abstratos

Método Virtual (Com Implementação Padrão)

// Na classe base Personagem
public virtual void Descansar()
{
    Console.WriteLine($"{Nome} está descansando...");
}

// Na classe Heroi (pode sobrescrever ou não)
public override void Descansar()
{
    Console.WriteLine($"{Nome} descansa na Batcaverna...");
}

// Na classe Vilao (usa a implementação padrão ou sobrescreve)
// Se não sobrescrever, usa a de Personagem

Método Abstrato (Sem Implementação)

// Na classe base Personagem (abstrata)
public abstract void UsarPoder();  // Sem implementação

// Na classe Heroi (DEVE implementar)
public override void UsarPoder()
{
    Console.WriteLine($"{Nome} usa poder para proteger!");
}

// Na classe Vilao (DEVE implementar, diferente de Heroi)
public override void UsarPoder()
{
    Console.WriteLine($"{Nome} usa poder para causar caos!");
}

Polimorfismo: Sobrecarga de Métodos

Exemplo: Múltiplos Construtores

// TÓPICO: Sobrecarga (Overload)
// Múltiplos métodos com mesmo nome, mas parâmetros diferentes
public class Heroi : Personagem
{
    public string Equipe { get; set; }

    // Construtor 1: Com equipe
    public Heroi(string nome, int nivel, string equipe) : base(nome, nivel)
    {
        Equipe = equipe;
    }

    // Construtor 2: Sem equipe (sobrecarga)
    public Heroi(string nome, int nivel) : base(nome, nivel)
    {
        Equipe = "Sem equipe";
    }

    // TÓPICO: Sobrecarga de Métodos
    // Múltiplos métodos SalvarVida com parâmetros diferentes
    public void SalvarVida()
    {
        VidasSalvas++;
        Console.WriteLine($"{Nome} salvou uma vida!");
    }

    // Sobrecarga: Salvar múltiplas vidas
    public void SalvarVida(int quantidade)
    {
        VidasSalvas += quantidade;
        Console.WriteLine($"{Nome} salvou {quantidade} vidas de uma vez!");
    }

    // Sobrecarga: Salvar vida com descrição
    public void SalvarVida(string descricao)
    {
        VidasSalvas++;
        Console.WriteLine($"{Nome} salvou uma vida: {descricao}");
    }
}

// TÓPICO: Uso de Sobrecarga
Heroi batman = new Heroi("Batman", 85, "Liga da Justiça");
batman.SalvarVida();                    // Chama SalvarVida() sem parâmetros
batman.SalvarVida(5);                    // Chama SalvarVida(int)
batman.SalvarVida("Criança em perigo");  // Chama SalvarVida(string)

Exemplo Completo: Batalha com Polimorfismo

// TÓPICO: Polimorfismo em Ação Real
// Sistema de batalha que funciona com qualquer personagem

public class Batalha
{
    // TÓPICO: Método que Aceita Classe Base
    // Funciona com Heroi, Vilao, ou qualquer classe derivada de Personagem
    public static void IniciarBatalha(Personagem atacante, Personagem defensor)
    {
        Console.WriteLine($"=== BATALHA ===");
        Console.WriteLine($"{atacante.Nome} vs {defensor.Nome}");
        Console.WriteLine();

        // TÓPICO: Polimorfismo
        // Cada personagem usa poder de forma diferente
        Console.WriteLine($"{atacante.Nome} ataca:");
        atacante.UsarPoder();  // Polimorfismo!

        Console.WriteLine($"{defensor.Nome} se defende:");
        defensor.UsarPoder();  // Polimorfismo!

        Console.WriteLine();
    }
}

// TÓPICO: Usando Polimorfismo
// Criando personagens diferentes
Heroi batman = new Heroi("Batman", 85, "Liga da Justiça");
Vilao coringa = new Vilao("Coringa", 80, "Legião do Mal");
Heroi superman = new Heroi("Superman", 100, "Liga da Justiça");

// TÓPICO: Passando Objetos Diferentes para Mesmo Método
// O método aceita qualquer Personagem (herói ou vilão)
Batalha.IniciarBatalha(batman, coringa);    // Herói vs Vilão
Batalha.IniciarBatalha(superman, coringa);  // Herói vs Vilão
Batalha.IniciarBatalha(coringa, batman);    // Vilão vs Herói (invertido)

Polimorfismo: Verificação de Tipo

// TÓPICO: Verificar Tipo em Tempo de Execução
// Às vezes precisamos saber o tipo real do objeto
foreach (Personagem personagem in personagens)
{
    // TÓPICO: Operador 'is'
    // Verifica se o objeto é de um tipo específico
    if (personagem is Heroi)
    {
        // TÓPICO: Cast (Conversão de Tipo)
        // Converte Personagem para Heroi para acessar métodos específicos
        Heroi heroi = (Heroi)personagem;
        heroi.SalvarVida();  // Método só de heróis
    }
    else if (personagem is Vilao)
    {
        Vilao vilao = (Vilao)personagem;
        vilao.ExecutarPlano();  // Método só de vilões
    }
}

// TÓPICO: Operador 'as' (Cast Seguro)
// Tenta converter, retorna null se não conseguir (não lança exceção)
Heroi heroi2 = personagem as Heroi;
if (heroi2 != null)
{
    heroi2.SalvarVida();
}

Vantagens do Polimorfismo

  1. Flexibilidade: Código funciona com objetos diferentes
  2. Extensibilidade: Fácil adicionar novos tipos sem modificar código existente
  3. Manutenibilidade: Código mais organizado e fácil de manter
  4. Reutilização: Mesmo código funciona com diferentes objetos

Resumo

Próxima Aula

Na próxima aula, veremos Try-Catch** e tratamento de exceções.