🎓 Aulas de Programação Orientada a Objetos

Universo DC - Aprenda POO com exemplos práticos

Objetivo da Aula

Entender o conceito de Herança em POO, criando classes derivadas (Herói e Vilão) a partir da classe base Personagem.

Aula 02: Herança - Heróis e Vilões


Conceito de Herança

O que é Herança?

Herança é um mecanismo que permite criar uma nova classe baseada em uma classe existente. A nova classe herda todas as propriedades e métodos da classe base. Analogia: Se Personagem é um veículo genérico, Herói e Vilão são tipos específicos de veículos (carro, moto) que herdam características do veículo genérico.

Símbolo de Herança

Em C#, usamos : (dois pontos) para indicar herança:

public class Herói : Personagem
{
    // Herói herda tudo de Personagem
}

Hierarquia no Universo DC

Personagem (Classe Base/Pai)
    ├── Herói (Classe Derivada/Filha)
    │   ├── Batman (Objeto)
    │   ├── Superman (Objeto)
    │   └── Flash (Objeto)
    │
    └── Vilão (Classe Derivada/Filha)
        ├── Coringa (Objeto)
        ├── Lex Luthor (Objeto)
        └── Darkseid (Objeto)

Implementação: Classe Herói

Versão Completa

// TÓPICO: Herança
// 'Herói' herda de 'Personagem' usando ':'
// Isso significa que Herói tem TUDO que Personagem tem, MAIS suas próprias características
public class Heroi : Personagem
{
    // TÓPICO: Propriedades Específicas
    // Propriedades que só os heróis têm
    private string _equipe;  // Equipe a que pertence (Liga da Justiça, etc.)

    public string Equipe
    {
        get { return _equipe; }
        set { _equipe = value; }
    }

    private int _vidasSalvas;  // Quantas vidas o herói já salvou

    public int VidasSalvas
    {
        get { return _vidasSalvas; }
        set
        {
            // Validação: não pode ser negativo
            _vidasSalvas = value >= 0 ? value : 0;
        }
    }

    // TÓPICO: Construtor da Classe Derivada
    // O construtor da classe filha DEVE chamar o construtor da classe pai
    // Usamos 'base()' para chamar o construtor da classe base
    public Heroi(string nome, int nivel, string equipe)
        : base(nome, nivel)  // Chama o construtor de Personagem
    {
        // Inicializa propriedades específicas de Herói
        this.Equipe = equipe;
        this.VidasSalvas = 0;  // Começa com zero vidas salvas
    }

    // TÓPICO: Métodos Específicos
    // Métodos que só heróis podem fazer

    // Método para salvar vidas
    public void SalvarVida()
    {
        VidasSalvas++;
        Console.WriteLine($"{Nome} salvou uma vida! Total: {VidasSalvas} vidas salvas.");
    }

    // Método para se juntar à equipe
    public void JuntarEquipe(string novaEquipe)
    {
        Equipe = novaEquipe;
        Console.WriteLine($"{Nome} se juntou à {Equipe}!");
    }

    // TÓPICO: Sobrescrita de Métodos (Override)
    // Podemos redefinir métodos da classe base
    // Usamos 'override' para sobrescrever métodos virtuais da classe pai
    public override void Apresentar()
    {
        // Chama o método da classe base e adiciona informações extras
        base.Apresentar();  // Chama Apresentar() de Personagem
        Console.WriteLine($"Sou um herói da {Equipe} e já salvei {VidasSalvas} vidas!");
    }
}

Versão Abreviada

// Versão mais concisa usando propriedades auto-implementadas
public class Heroi : Personagem
{
    // Propriedades auto-implementadas (modo abreviado)
    public string Equipe { get; set; }
    public int VidasSalvas { get; set; }

    // Construtor abreviado
    public Heroi(string nome, int nivel, string equipe) : base(nome, nivel)
    {
        Equipe = equipe;
        VidasSalvas = 0;
    }

    // Métodos abreviados com expressões lambda (quando possível)
    public void SalvarVida() =>
        Console.WriteLine($"{Nome} salvou uma vida! Total: {++VidasSalvas} vidas salvas.");

    public void JuntarEquipe(string novaEquipe)
    {
        Equipe = novaEquipe;
        Console.WriteLine($"{Nome} se juntou à {Equipe}!");
    }

    // Sobrescrita do método Apresentar
    public override void Apresentar()
    {
        base.Apresentar();
        Console.WriteLine($"Sou um herói da {Equipe} e já salvei {VidasSalvas} vidas!");
    }
}

Implementação: Classe Vilão

Versão Completa

// TÓPICO: Herança - Classe Vilão
// Vilão também herda de Personagem
public class Vilao : Personagem
{
    // Propriedades específicas de vilões
    private string _organizacao;  // Organização criminosa

    public string Organizacao
    {
        get { return _organizacao; }
        set { _organizacao = value; }
    }

    private int _planosExecutados;  // Quantos planos maléficos foram executados

    public int PlanosExecutados
    {
        get { return _planosExecutados; }
        set { _planosExecutados = value >= 0 ? value : 0; }
    }

    // Construtor
    public Vilao(string nome, int nivel, string organizacao)
        : base(nome, nivel)  // Chama construtor de Personagem
    {
        this.Organizacao = organizacao;
        this.PlanosExecutados = 0;
    }

    // Métodos específicos de vilões
    public void ExecutarPlano()
    {
        PlanosExecutados++;
        Console.WriteLine($"{Nome} executou um plano maléfico! Total: {PlanosExecutados} planos.");
    }

    public void JuntarOrganizacao(string novaOrganizacao)
    {
        Organizacao = novaOrganizacao;
        Console.WriteLine($"{Nome} se juntou à {Organizacao}!");
    }

    // Sobrescrita do método Apresentar
    public override void Apresentar()
    {
        base.Apresentar();
        Console.WriteLine($"Sou um vilão da {Organizacao} e já executei {PlanosExecutados} planos!");
    }
}

Versão Abreviada

public class Vilao : Personagem
{
    public string Organizacao { get; set; }
    public int PlanosExecutados { get; set; }

    public Vilao(string nome, int nivel, string organizacao) : base(nome, nivel)
    {
        Organizacao = organizacao;
        PlanosExecutados = 0;
    }

    public void ExecutarPlano() =>
        Console.WriteLine($"{Nome} executou um plano! Total: {++PlanosExecutados} planos.");

    public void JuntarOrganizacao(string novaOrganizacao)
    {
        Organizacao = novaOrganizacao;
        Console.WriteLine($"{Nome} se juntou à {Organizacao}!");
    }

    public override void Apresentar()
    {
        base.Apresentar();
        Console.WriteLine($"Sou um vilão da {Organizacao} e já executei {PlanosExecutados} planos!");
    }
}

Atualizando a Classe Base Personagem

Para permitir sobrescrita de métodos, a classe base deve ter métodos virtual:

public class Personagem
{
    public string Nome { get; set; }
    public int Nivel { get; set; }

    public Personagem(string nome, int nivel)
    {
        Nome = nome;
        Nivel = nivel;
    }

    // TÓPICO: Método Virtual
    // 'virtual' permite que classes filhas sobrescrevam este método
    public virtual void Apresentar()
    {
        Console.WriteLine($"Olá! Eu sou {Nome}, nível {Nivel}!");
    }

    public void SubirNivel()
    {
        Nivel++;
        Console.WriteLine($"{Nome} subiu para o nível {Nivel}!");
    }
}

Criando Objetos das Classes Derivadas

Criando Heróis

// TÓPICO: Polimorfismo
// Podemos tratar objetos de classes derivadas como se fossem da classe base
// Mas eles mantêm suas características específicas

// Criando heróis (objetos da classe Heroi)
Heroi batman = new Heroi("Batman", 85, "Liga da Justiça");
Heroi superman = new Heroi("Superman", 100, "Liga da Justiça");
Heroi flash = new Heroi("Flash", 90, "Liga da Justiça");

// Usando métodos específicos de heróis
batman.SalvarVida();        // Método só de heróis
batman.SalvarVida();
superman.SalvarVida();

// Usando métodos herdados
batman.SubirNivel();        // Método herdado de Personagem
batman.Apresentar();         // Método sobrescrito

Criando Vilões

// Criando vilões (objetos da classe Vilao)
Vilao coringa = new Vilao("Coringa", 80, "Legião do Mal");
Vilao lexLuthor = new Vilao("Lex Luthor", 75, "Legião do Mal");
Vilao darkseid = new Vilao("Darkseid", 95, "Apokolips");

// Usando métodos específicos de vilões
coringa.ExecutarPlano();    // Método só de vilões
lexLuthor.ExecutarPlano();

// Usando métodos herdados
darkseid.SubirNivel();      // Método herdado de Personagem
coringa.Apresentar();        // Método sobrescrito

Polimorfismo com Lista

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

// Adicionando heróis e vilões na mesma lista
personagens.Add(new Heroi("Batman", 85, "Liga da Justiça"));
personagens.Add(new Heroi("Superman", 100, "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"));

// Iterando sobre a lista
foreach (Personagem personagem in personagens)
{
    // Cada objeto chama sua própria versão do método Apresentar()
    personagem.Apresentar();  // Polimorfismo em ação!
}

Comparação: Herança Completa vs Abreviada

AspectoModo CompletoModo Abreviado
PropriedadesCampos privados + get/set explícitosAuto-implementadas { get; set; }
Construtorthis.Propriedade = valorPropriedade = valor
MétodosBlocos { } completosExpressões lambda quando possível
LegibilidadeMais verboso, mais explícitoMais conciso, menos linhas

Vantagens da Herança

  1. Reutilização de Código: Não precisa reescrever código comum
  2. Organização: Código mais organizado e hierárquico
  3. Manutenção: Mudanças na classe base afetam todas as derivadas
  4. Polimorfismo: Tratar objetos diferentes de forma uniforme

Resumo

Próxima Aula

Na próxima aula, veremos Classes Abstratas e como criar classes que não podem ser instanciadas diretamente.