Introdução
Definição: expor o "o quê" e esconder o "como". É a diferença entre uma interface de operação e sua implementação.
Isso normalmente é confundido com encapsulamento, mas são coisas diferentes: encapsulamento é sobre proteção do estado; abstração é sobre simplificação da complexidade — reduzir um problema complexo a um modelo mais simples de interagir.
public interface INotificador
{
void Enviar(string mensagem, string destinatario);
}
public class NotificadorEmail : INotificador
{
public void Enviar(string mensagem, string destinatario)
{
// conecta em SMTP, monta o corpo do e-mail, trata retry, etc — tudo escondido
Console.WriteLine($"E-mail enviado para {destinatario}");
}
}
public class NotificadorSms : INotificador
{
public void Enviar(string mensagem, string destinatario)
{
// chama API de SMS, formata número, etc — também escondido
Console.WriteLine($"SMS enviado para {destinatario}");
}
}
Quem usa INotificador não sabe (nem precisa saber) se por trás tem uma chamada SMTP ou uma API REST de SMS. Só conhece o contrato: Enviar(mensagem, destinatario).
Níveis de abstração — pense numa aplicação em camadas: Controller chama IPedidoService, que chama IPedidoRepository, que fala com o banco. Cada camada abstrai a complexidade da camada de baixo. Isso é abstração acontecendo em escala arquitetural, não só numa classe.
Abstração vazada (leaky abstraction) é o antipadrão aqui: quando detalhes de implementação "vazam" pro contrato. Exemplo clássico: um método INotificador.Enviar() que lança SmtpException — isso força quem usa a interface a conhecer detalhes de uma implementação específica (e-mail), quebrando a abstração.
Exemplo aplicado a jogo
Quando você aperta "Atacar" no controle, você não calcula chance de crítico, multiplicador elemental, redução por armadura — o jogo esconde essa complexidade toda atrás de um botão simples. Isso é abstração.
class Personagem
{
// ...
public void Atacar(Personagem alvo)
{
int dano = CalcularDano(); // fórmula escondida
alvo.TomarDano(dano);
Console.WriteLine($"{Nome} atacou {alvo.Nome} causando {dano} de dano!");
}
private int CalcularDano()
{
bool critico = new Random().Next(100) < 15; // 15% de chance
int danoBase = 20;
return critico ? danoBase * 2 : danoBase;
}
}
Quem chama personagem.Atacar(inimigo) não faz ideia de que existe cálculo de crítico rolando por trás. Só vê a ação. É exatamente essa "caixa preta simples por fora, complexa por dentro" que é a abstração.
Top comments (0)