Pular para o conteúdo
.NETInterfaces e classes abstratas
Módulo 01Fundamentos da Plataforma e da Linguagem

Interfaces e classes abstratas

intermediario 30 min de leitura·Atualizado · .NET 9
Resumo

Uma interface é um contrato puro (o "o quê"), sem estado. Uma classe abstrata é uma base parcial (o "o quê" + parte do "como"). Programar contra abstrações é a base da injeção de dependência e da testabilidade.

1. Objetivos de Aprendizagem#

  • Declarar e implementar interfaces.
  • Diferenciar interface de classe abstrata.
  • Entender por que "programar para interfaces" habilita DI e testes.

2. Pré-requisitos#

  • Herança e polimorfismo (tópico 5.2).

3. Conceito#

  • Interface (interface IX): só declara membros (métodos, propriedades). Uma classe pode implementar várias interfaces. Não tem estado.
  • Classe abstrata (abstract class): pode ter estado e implementação parcial, com membros abstract que as derivadas devem completar. Herança única.

O porquê: depender de IRepositorioProduto (interface) em vez de uma implementação concreta permite trocar a implementação (SQL, memória, mock de teste) sem mudar quem consome. É o alicerce da injeção de dependência (Módulo 12).

4. Mão na Massa#

4.1. Setup#

Shell
dotnet new console -n Catalog.Contratos
cd Catalog.Contratos

4.2. Implementação Passo a Passo#

  1. Interface (contrato):
C#
public interface INotificador
{
    void Enviar(string destino, string mensagem);
}
  1. Implementações intercambiáveis:
C#
public class NotificadorEmail : INotificador
{
    public void Enviar(string destino, string mensagem) =>
        Console.WriteLine($"[email->{destino}] {mensagem}");
}

public class NotificadorFake : INotificador   // útil em testes
{
    public void Enviar(string destino, string mensagem) { /* no-op */ }
}
  1. Consumidor depende do contrato, não da implementação:
C#
public class ServicoPedido
{
    private readonly INotificador _notificador;
    public ServicoPedido(INotificador notificador) => _notificador = notificador;

    public void Confirmar(string email) =>
        _notificador.Enviar(email, "Pedido confirmado!");
}

new ServicoPedido(new NotificadorEmail()).Confirmar("ana@x.com");

4.3. Executando#

Shell
dotnet run

5. Exemplo Completo#

ServicoPedido funciona com qualquer INotificador. Em produção você injeta NotificadorEmail; em teste, NotificadorFake — sem alterar o serviço.

6. Boas Práticas e Armadilhas#

FaçaEvite
Depender de interfaces nas fronteiras (serviços, repositórios)Instanciar dependências concretas com new dentro da classe
Interfaces pequenas e focadas (ISP)Interfaces "gigantes" com dezenas de membros
Classe abstrata quando há estado/implementação comumInterface quando você precisa compartilhar código concreto
Nota

interfaces podem ter membros com implementação padrão (default interface methods), mas use isso com parcimônia — na maioria dos casos, o contrato puro é mais claro.

7. Segurança e Produção#

  • Depender de abstrações facilita substituir implementações inseguras/legadas e escrever testes que não tocam recursos externos (rede, banco).

8. Exercícios#

  • Fácil: crie IArmazenamento com Salvar(string).
  • Médio: implemente duas versões (arquivo e memória).
  • Desafio: faça um serviço que dependa de IArmazenamento e teste-o com a versão em memória.

9. Resumo#

Interface = contrato puro (herança múltipla); classe abstrata = base parcial com estado (herança única). Programar contra interfaces habilita DI e testes.

10. Próximos Passos#

Encerramos OOP. A seguir, recursos de C# moderno que deixam o código mais expressivo.

11. Referências#

05-03 — Interfaces e classes abstratas | Curso ASP.NET Core