DEV Community

Yuri Peixinho
Yuri Peixinho

Posted on

POO: Encapsulamento

Introdução

O conceito de encapusalento é primordial para proteger nossas classes. Vamos ser didáticos aqui e fingir que estamos desenvolvendo um jogo de RPG. Pensa na vida (HP) do personagem como aquela barrinha vermelha no topo da tela. Se qualquer parte do código puder mexer nela direto, é fácil alguém, por engano, jogar a vida pra -500 ou deixar passar do máximo — bug feio, barra quebrada.

class Personagem
{
    public string Nome { get; }
    public int VidaMaxima { get; }
    private int _vida;              // ninguém mexe aqui de fora
    public int Vida => _vida;       // só leitura

    public Personagem(string nome, int vidaMaxima)
    {
        Nome = nome;
        VidaMaxima = vidaMaxima;
        _vida = vidaMaxima;
    }

    public void TomarDano(int dano)
    {
        _vida = Math.Max(0, _vida - dano);       // nunca fica negativo
        if (_vida == 0) Console.WriteLine($"{Nome} foi derrotado!");
    }

    public void Curar(int quantidade)
    {
        _vida = Math.Min(VidaMaxima, _vida + quantidade); // nunca passa do máximo
    }
}
Enter fullscreen mode Exit fullscreen mode

Repara: personagem.Vida = -50; nem compila. A única forma de mexer na vida é passando pelas regras (TomarDano, Curar), que garantem que ela nunca sai do intervalo válido. Isso é encapsulamento — o dado protegido pela lógica que mora junto dele.

Um detalhe importante é: não é só "usar private", é agrupar dados e o comportamento que os manipula, escondendo os detalhes internos e expondo uma interface controlada. O objetivo é garantir que o objeto nunca fique num estado inválido.

Os dois níveis de encapsulamento

Dois níveis de encapsulamento que gente costuma confundir:

  • Data hiding — esconder os campos (private decimal _saldo).
  • Information hiding (mais amplo) — esconder a implementação, não só os dados. Exemplo: trocar a implementação interna de uma Lista de array pra lista ligada sem que ninguém que usa a classe perceba.

Nível de acesso em C

É importante e cai muito bem dominar todos, não só o public/private

public class Exemplo
{
    private int _a;      // só dentro da própria classe
    protected int _b;    // classe e subclasses
    internal int _c;     // mesmo assembly
    protected internal int _d; // subclasses OU mesmo assembly
    private protected int _e;  // subclasses DENTRO do mesmo assembly
    public int _f;       // qualquer um
}
Enter fullscreen mode Exit fullscreen mode

Erro comum

Um erro comum é expor um campo mutável de referência (lista, array) via getter público quebra o encapsulamento mesmo com private set:

class Pedido
{
    private List<string> _itens = new();
    public List<string> Itens => _itens; // PERIGO: quem chamar Itens.Add() muda o estado interno direto
}
Enter fullscreen mode Exit fullscreen mode

O fix é retornar uma cópia ou uma interface somente-leitura: IReadOnlyList<string> Itens => _itens.AsReadOnly();

Top comments (0)