🎓 Aulas de Programação Orientada a Objetos

Universo DC - Aprenda POO com exemplos práticos

Objetivo da Aula

Entender o conceito de Encapsulamento e os modificadores de acesso (public, private, protected) em C#.

Aula 07: Encapsulamento e Modificadores de Acesso


Conceito de Encapsulamento

O que é Encapsulamento?

Encapsulamento é o princípio de ocultar detalhes internos de uma classe e expor apenas o que é necessário. É como uma cápsula que protege o conteúdo interno. Analogia: É como um carro. Você não precisa saber como o motor funciona internamente, apenas usa o volante e os pedais (interface pública).

Modificadores de Acesso

Public (Público)

// TÓPICO: Modificador Public
// 'public' significa que pode ser acessado de QUALQUER lugar
public class Personagem
{
    // TÓPICO: Propriedade Pública
    // Pode ser acessada de qualquer classe
    public string Nome { get; set; }

    // TÓPICO: Método Público
    // Pode ser chamado de qualquer lugar
    public void Apresentar()
    {
        Console.WriteLine($"Olá! Eu sou {Nome}!");
    }
}

// TÓPICO: Acesso Público
// Qualquer classe pode acessar
Personagem batman = new Personagem();
batman.Nome = "Batman";        // ✅ Pode acessar (é público)
batman.Apresentar();           // ✅ Pode chamar (é público)

Private (Privado)

// TÓPICO: Modificador Private
// 'private' significa que só pode ser acessado DENTRO da própria classe
public class Personagem
{
    // TÓPICO: Campo Privado
    // Só pode ser acessado dentro desta classe
    private int _energia;  // Convenção: campos privados começam com _

    // TÓPICO: Propriedade Pública que Acessa Campo Privado
    // Encapsulamento: controla como o campo privado é acessado
    public int Energia
    {
        get { return _energia; }
        set
        {
            // TÓPICO: Validação no Setter
            // Protege o campo privado com validação
            if (value >= 0 && value <= 100)
            {
                _energia = value;
            }
            else
            {
                throw new ArgumentException("Energia deve estar entre 0 e 100!");
            }
        }
    }

    // TÓPICO: Método Privado
    // Só pode ser chamado dentro desta classe
    private void RecuperarEnergia()
    {
        if (_energia < 100)
        {
            _energia += 10;
            Console.WriteLine("Energia recuperada!");
        }
    }

    // TÓPICO: Método Público que Usa Método Privado
    // Encapsulamento: método privado é usado internamente
    public void Descansar()
    {
        Console.WriteLine($"{Nome} está descansando...");
        RecuperarEnergia();  // ✅ Pode chamar (está na mesma classe)
    }
}

// TÓPICO: Tentativa de Acesso Privado (ERRO)
Personagem batman = new Personagem();
// batman._energia = 50;        // ❌ ERRO! Campo privado não pode ser acessado
// batman.RecuperarEnergia();   // ❌ ERRO! Método privado não pode ser chamado
batman.Energia = 50;            // ✅ OK! Usa propriedade pública
batman.Descansar();             // ✅ OK! Método público chama método privado internamente

Protected (Protegido)

// TÓPICO: Modificador Protected
// 'protected' significa que pode ser acessado pela classe E pelas classes filhas (herança)
public class Personagem
{
    // TÓPICO: Campo Protected
    // Pode ser acessado por esta classe e classes filhas
    protected int _experiencia;  // Experiência é protegida

    // TÓPICO: Propriedade Protected
    // Classes filhas podem acessar
    protected int Experiencia
    {
        get { return _experiencia; }
        set { _experiencia = value >= 0 ? value : 0; }
    }

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

    // TÓPICO: Método Protected
    // Só pode ser chamado dentro da classe ou classes filhas
    protected void GanharExperiencia(int quantidade)
    {
        _experiencia += quantidade;
        Console.WriteLine($"{Nome} ganhou {quantidade} de experiência!");

        // TÓPICO: Lógica Interna
        // Verifica se subiu de nível
        if (_experiencia >= Nivel * 100)
        {
            SubirNivel();
            _experiencia = 0;  // Reseta experiência
        }
    }

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

// TÓPICO: Classe Filha Acessando Protected
public class Heroi : Personagem
{
    public Heroi(string nome, int nivel) : base(nome, nivel)
    {
        // TÓPICO: Acesso a Membros Protected
        // Classes filhas podem acessar membros protected da classe base
        _experiencia = 0;  // ✅ Pode acessar (é protected)
        Experiencia = 0;   // ✅ Pode acessar (é protected)
    }

    public void CompletarMissao()
    {
        // TÓPICO: Usando Método Protected
        // Pode chamar método protected da classe base
        GanharExperiencia(50);  // ✅ Pode chamar (é protected)
        Console.WriteLine($"{Nome} completou uma missão!");
    }
}

// TÓPICO: Tentativa de Acesso Protected de Fora (ERRO)
Heroi batman = new Heroi("Batman", 85);
// batman._experiencia = 100;      // ❌ ERRO! Protected não pode ser acessado de fora
// batman.GanharExperiencia(50);  // ❌ ERRO! Método protected não pode ser chamado de fora
batman.CompletarMissao();         // ✅ OK! Método público que usa método protected internamente

Tabela de Modificadores de Acesso

ModificadorAcesso na Própria ClasseAcesso em Classes FilhasAcesso de Outras Classes
public✅ SIM✅ SIM✅ SIM
private✅ SIM❌ NÃO❌ NÃO
protected✅ SIM✅ SIM❌ NÃO
internal✅ SIM (mesmo assembly)✅ SIM (mesmo assembly)✅ SIM (mesmo assembly)
protected internal✅ SIM✅ SIM✅ SIM (mesmo assembly)

Exemplo Completo: Encapsulamento

Versão Completa com Encapsulamento

// TÓPICO: Classe com Encapsulamento Completo
public class Personagem
{
    // TÓPICO: Campos Privados (Encapsulados)
    // Detalhes internos não devem ser acessados diretamente
    private int _vida;
    private int _energia;
    private int _experiencia;

    // TÓPICO: Propriedades Públicas com Validação
    // Controlam o acesso aos campos privados
    public string Nome { get; set; }

    public int Vida
    {
        get { return _vida; }
        set
        {
            // TÓPICO: Validação no Setter
            // Protege o campo privado
            if (value < 0)
                _vida = 0;
            else if (value > 100)
                _vida = 100;
            else
                _vida = value;
        }
    }

    public int Energia
    {
        get { return _energia; }
        set
        {
            _energia = (value < 0) ? 0 : (value > 100) ? 100 : value;
        }
    }

    // TÓPICO: Propriedade Somente Leitura
    // Pode ler, mas não pode modificar diretamente
    public int Experiencia
    {
        get { return _experiencia; }
        // Sem set - só pode ser modificada através de métodos
    }

    // TÓPICO: Construtor
    public Personagem(string nome)
    {
        Nome = nome;
        _vida = 100;
        _energia = 100;
        _experiencia = 0;
    }

    // TÓPICO: Métodos Públicos (Interface da Classe)
    // Expõe funcionalidades de forma controlada

    public void ReceberDano(int dano)
    {
        // TÓPICO: Lógica Interna Protegida
        // Usa propriedade que tem validação
        Vida -= dano;
        Console.WriteLine($"{Nome} recebeu {dano} de dano! Vida: {Vida}");

        if (Vida <= 0)
        {
            Console.WriteLine($"{Nome} foi derrotado!");
        }
    }

    public void UsarEnergia(int quantidade)
    {
        if (Energia >= quantidade)
        {
            Energia -= quantidade;
            Console.WriteLine($"{Nome} usou {quantidade} de energia! Restante: {Energia}");
        }
        else
        {
            Console.WriteLine($"{Nome} não tem energia suficiente!");
        }
    }

    // TÓPICO: Método Privado (Detalhe de Implementação)
    // Não deve ser chamado de fora da classe
    private void GanharExperienciaInterna(int quantidade)
    {
        _experiencia += quantidade;
    }

    // TÓPICO: Método Público que Usa Método Privado
    // Encapsula a lógica interna
    public void CompletarAcao()
    {
        GanharExperienciaInterna(10);  // Usa método privado
        Console.WriteLine($"{Nome} completou uma ação! Experiência: {Experiencia}");
    }
}

Versão Abreviada

// TÓPICO: Encapsulamento Simplificado
public class Personagem
{
    // Propriedades auto-implementadas (mais simples)
    public string Nome { get; set; }

    // Propriedade com validação abreviada
    private int _vida;
    public int Vida
    {
        get => _vida;
        set => _vida = (value < 0) ? 0 : (value > 100) ? 100 : value;
    }

    // Propriedade somente leitura
    public int Experiencia { get; private set; }

    public Personagem(string nome)
    {
        Nome = nome;
        Vida = 100;
        Experiencia = 0;
    }

    // Métodos abreviados
    public void ReceberDano(int dano) => Vida -= dano;

    public void CompletarAcao() => Experiencia += 10;
}

Benefícios do Encapsulamento

  1. Proteção de Dados: Campos privados não podem ser modificados incorretamente
  2. Validação: Propriedades podem validar dados antes de atribuir
  3. Flexibilidade: Pode mudar implementação interna sem afetar código externo
  4. Manutenibilidade: Código mais organizado e fácil de manter

Resumo

Próxima Aula

Na próxima aula, veremos Propriedades e Métodos Estáticos.