1. Introdução
Imagina que você tá projetando um carro moderno. Por dentro — centenas de peças complicadas, eletrônica sensível, ajustes finos. É óbvio que ninguém deveria simplesmente abrir o módulo de controle do motor e começar a mexer nos parafusos. Se todo mundo meter a mão onde não deve, o carro pode começar a agir de forma imprevisível, e você vai ter que fazer revisão pra descobrir quem quebrou o quê.
No mundo da programação é igualzinho. Quando você cria uma classe, quer proteger o que tem dentro dela das mãos dos outros — pra ninguém estragar dados importantes sem querer ou mexer em métodos que o mundo externo nem deveria saber que existem. Essa é a ideia do encapsulamento — um dos três princípios chave da programação orientada a objetos.
Encapsulamento serve pra esconder detalhes da implementação e deixar bem claro o que tá disponível "por fora" e o que tem que ficar só por dentro. É tipo abrir o porta-luvas pro usuário, mas deixar o capô bem trancado. A própria classe decide quais dados mostrar pro código externo e quais manter em segredo. Assim, o código fica mais confiável, lógico e fácil de dar manutenção.
Falando de forma mais formal, encapsulamento é um jeito de juntar dados (campos) e comportamento (métodos) relacionados numa estrutura só, limitando o acesso direto aos componentes internos do objeto.
2. Modificadores de acesso: protegendo seu território
No C# (e em outras linguagens OOP) encapsulamento é feito usando modificadores de acesso. São tipo "etiquetas" que dizem quais membros da classe (campos, métodos, propriedades, etc.) podem ser acessados de fora e quais só de dentro.
A gente já viu eles antes, mas bora relembrar e dar uma expandida na lista de modificadores:
| Modificador | Disponível para... |
|---|---|
|
Todo mundo! Qualquer código no projeto (e fora dele, se o projeto for uma biblioteca) |
|
Só de dentro da própria classe |
|
Da classe e de todos os filhos dela |
|
Só dentro do assembly (projeto) atual |
|
Ou do assembly atual, ou de um filho |
|
Só do filho dentro do assembly atual |
Nessa aula vamos focar nos mais usados: public, private e dar uma passada rápida no protected, pra não fritar o cérebro.
Separando o que é interno e externo
Bora escrever uma classe Dog:
public class Dog
{
public string Name;
public int Age;
public void Bark()
{
Console.WriteLine($"{Name} fala: Au au!");
}
}
Aqui todos os campos e métodos estão com o modificador public. Isso quer dizer que qualquer um pode mudar o nome ou a idade do cachorro:
Dog rex = new Dog("Rex", 5);
rex.Name = "Bolinha"; // Mudança de identidade do nada!
rex.Age = -999; // Problemas sérios de idade
Mas os campos Name e Age são dados super importantes, que não dá pra deixar qualquer um mexer.
Não faça desse jeito
Se deixar tudo public, você corre o risco de quebrar a lógica da classe: qualquer interferência externa pode deixar o objeto inválido. Tipo, colocar idade negativa no cachorro ou dar um nome tipo "%$#!??".
3. Escondendo campos: usando private
Normalmente os campos da classe são privados (com o modificador private). Isso quer dizer que só dá pra mudar eles de dentro da própria classe, e de fora — nem pensar.
public class Dog
{
private string name;
private int age;
public void Bark()
{
Console.WriteLine($"{name} fala: Au au!");
}
}
Agora, se tentar acessar os campos direto de fora:
Dog rex = new Dog("Rex", 5);
rex.name = "Bolinha"; // Erro de compilação
O compilador já vai avisar: "Sem acesso!"
Por que ser tão rígido? Cadê a flexibilidade?
Toda a "flexibilidade" vem de métodos especiais ou propriedades (vamos falar mais delas na próxima aula), que deixam você controlar o acesso e mudar os dados só do jeito certo.
4. Encapsulamento na prática: exemplo com controle
Imagina que a gente quer que não dê pra colocar idade negativa no cachorro:
public class Dog
{
private string name;
private int age;
public Dog(string name, int age)
{
this.name = name;
if (age >= 0)
this.age = age;
else
this.age = 0; // Não deixa colocar idade "estranha"
}
public void Bark()
{
Console.WriteLine($"{name} fala: Au au!");
}
// Método pra mudar a idade de forma segura
public void SetAge(int newAge)
{
if (newAge >= 0)
age = newAge;
// Pode adicionar else: mensagem de valor inválido
}
}
Agora ninguém de fora consegue estragar os campos direto. Pra mudar a idade tem um método especial que faz a checagem.
5. Campos vs métodos de acesso (getters/setters)
Esse jeito — deixar os campos private e criar métodos pra mexer neles — é chamado de encapsulamento de dados (data encapsulation). Pra ler o valor do campo, normalmente criam métodos getter, e pra escrever — métodos setter.
public class Dog
{
private string name;
public Dog(string name)
{
this.name = name;
}
public string GetName()
{
return name;
}
public void SetName(string newName)
{
// Aqui dá pra checar se o nome é válido
name = newName;
}
}
Mas! Com as propriedades (properties) no C#, esses métodos são cada vez menos usados — propriedades deixam o código muito mais limpo e fácil (mais sobre isso na próxima aula).
6. Modificadores de acesso pra métodos e classes
Campos não são tudo! Modificadores de acesso também servem pra métodos (funções da classe) e até pras próprias classes.
Métodos que só são usados dentro da classe (tipo funções auxiliares pra lógica interna), normalmente são private.
Métodos públicos — são o chamado interface da classe (não confundir com a palavra-chave interface), ou seja, o que o usuário da classe pode usar.
7. Erros comuns ao trabalhar com encapsulamento
Erro nº1: tudo é declarado como public.
Parece que quanto mais coisa disponível, mais fácil de usar. Mas na real — isso abre acesso a partes internas da classe que não deveriam ser mexidas de fora. Esse código fica vulnerável e imprevisível, principalmente em projetos grandes.
Erro nº2: mudar o modificador de acesso quebra o código externo.
Quando faz refatoração, pode sem querer mudar o modificador de acesso de um método ou campo, e aí todo o resto do código que usava eles para de compilar ou começa a se comportar errado. Isso é especialmente crítico em APIs públicas.
Erro nº3: confundir variáveis locais com campos da classe.
Às vezes o dev esquece que a variável criada dentro do método só existe ali. Já os campos da classe — estão disponíveis em todos os métodos dela. Isso gera erros chatos, principalmente se os nomes das variáveis forem iguais.
Erro nº4: ignorar private e protected.
Muita gente tem medo de usar acesso restrito, achando que depois não vai conseguir acessar o que precisa. Mas encapsulamento é justamente isso — esconder o que não interessa, e mostrar só o que realmente importa.
GO TO FULL VERSION