Interfaces e o Contrato de Comportamento

Aula 6 — Programação Orientada a Objetos

Marcos M. Raimundo — Instituto de Computação, UNICAMP

2026-08-26

Proposta da Aula

A pergunta da Aula 5: como o compilador aceita Pagavel p = new Pix() e depois p = new Cartao()?

A resposta começa aqui: a Interface — o mecanismo de linguagem que torna a abstração Pagavel real.

Roteiro: contrato → interfaces modernas → tipos como comportamento → exceções como guardas.

Interfaces: o Contrato de Comportamento

A Interface Pagavel

public interface Pagavel {
    boolean pagamentoConfirmado(String idString); // sem corpo!
    String criarCobranca(double valor);           // sem estado!
}

Diz o quê, nunca como. Métodos são implicitamente public abstract.

Cumprindo o Contrato: Pix

public class Pix implements Pagavel {
    @Override
    public boolean pagamentoConfirmado(String idString) { return true; }
    @Override
    public String criarCobranca(double valor) { return "PIX-..."; }
}

Esquecer um método do contrato = erro de compilação, não bug em produção.

A Analogia da Tomada Elétrica

A tomada não sabe se é liquidificador ou TV — só exige o plugue certo. Um aparelho novo não exige refazer a fiação da casa.

Interfaces Modernas: Default, Static, Private

Default, Static, Private

static boolean isValorValido(double v) { return v > 0; }      // utilitario do tipo
default void processarComLog(double v) { validar(v); ... }    // herdavel
private void validar(double v) { ... }                        // interno (Java 9+)

Evolução sem ruptura: Pix.java nem precisa saber que processarComLog existe.

O “Mutador Cego”

default void aplicarJuros(double taxa) {
    double saldoAtual = getSaldo();
    setSaldo(saldoAtual * (1 + taxa)); // muta sem saber ONDE o dado mora
}

Interface = cérebro (regra); classe concreta = músculos (armazenamento). Mesma regra, zero duplicação.

O método default aplicarJuros muda o saldo do objeto. Isso significa que a interface passou a ter estado próprio?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Interfaces Modernas e o Mutador Cego

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. Um método default pode chamar outros métodos abstratos da mesma interface, confiando que a classe concreta os implementa.
  2. O método aplicarJuros armazena o novo saldo dentro da própria interface, num atributo privado.
  3. O padrão Mutador Cego funciona porque a interface conhece o “cérebro” (regra) e delega o armazenamento aos “músculos” (classe concreta).
  4. Um método static de interface pode ser chamado sem nenhuma instância de uma classe concreta.

Interfaces Modernas e o Mutador Cego — Resposta

Dica

  1. Verdadeiro — é assim que aplicarJuros chama getSaldo()/setSaldo().
  2. Falso — a interface continua sem nenhum atributo de instância; o estado mora na classe concreta.
  3. Verdadeiro — é a definição do Mutador Cego.
  4. Verdadeiro — métodos static pertencem ao tipo, não a uma instância.

Interface vs. Classe Abstrata

A Fronteira: o Estado

Interface Classe Abstrata
Estado Proibido Permitido
Herança Múltipla (implements) Única (extends)
Propósito O que faz O que é

Tipo = Comportamento, Não DNA

List<Pagavel> opcoes = clienteLogado.consultaMeiosPagamento();
Pagavel forma = opcoes.get(escolha - 1); // Pix, Boleto, Cartao — tanto faz
String id = forma.criarCobranca(total);  // escrito para a abstracao

Pix e Cartao sem nada em comum em dados — mesmo tipo Pagavel, porque ambos “sabem pagar”.

Uma interface pode ter métodos default com lógica de negócio real. Isso a transforma numa “classe disfarçada”? O que exatamente impede isso?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Interfaces e o Contrato de Tipo

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. Uma interface define o que um objeto faz, sem exigir compartilhamento de estrutura interna (“DNA”).
  2. Métodos default e static tornam a interface equivalente a uma classe comum, incluindo suporte a atributos de instância.
  3. Duas classes sem nenhum atributo em comum podem, ainda assim, ser do mesmo tipo se implementarem a mesma interface.
  4. Esquecer de implementar um método do contrato de uma interface é um erro detectado em tempo de compilação.

Interfaces e o Contrato de Tipo — Resposta

Dica

  1. Verdadeiro — é a definição de Tipo Puro desta aula.
  2. Falso — mesmo com default/static, a interface continua proibida de ter atributos de instância.
  3. Verdadeiro — é exatamente o caso de Pix e CartaoDeCredito.
  4. Verdadeiro — o compilador impede a compilação se o contrato não for cumprido.

Exceções como Guardas de Contrato

Fail-Fast no Contrato

public String criarCobranca(double valor) {
    if (valor <= 0) throw new IllegalArgumentException("Valor invalido: " + valor);
    return "PIX-ID-...";
}

O compilador aceita qualquer double. A exceção protege o que o tipo não consegue expressar.

O Erro de Silenciar

Retornar null/0/false só empurra o erro para uma linha distante — um NullPointerException sem relação óbvia com a causa real.

O Try-Catch como Contenção

try {
    String id = formaEscolhida.criarCobranca(total);
} catch (IllegalArgumentException e) {
    view.exibirErro("Erro no pagamento: " + e.getMessage());
}

Baixo nível lança; alto nível decide como reagir.

Três Novos Contratos, Mesmo Padrão

public interface Notificavel { void enviar(String d, String m) throws NotificationException; }
public interface EstrategiaDesconto { double aplicar(double valorOriginal); }
public interface ServicoLogistico { String solicitarRastreio(Pedido p) throws CarrierUnavailableException; }

Exceção = cláusula do contrato: “prometo tentar, mas posso falhar — e aviso formalmente”.

Por que “lançar uma exceção” é descrito nesta aula como um ato de honestidade do objeto, e “tratá-la” como um ato de resiliência do sistema?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Exceções como Guardas de Contrato

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. O compilador é suficiente para impedir que um preço negativo seja aceito por um método que recebe double.
  2. Retornar null ou 0 para sinalizar um erro é uma prática que só adia a descoberta do problema real.
  3. Segundo a diretriz desta aula, componentes de baixo nível devem lançar exceções, e componentes de alto nível devem decidir como reagir.
  4. Um throws NotificationException na assinatura de um método é uma forma de tornar explícita uma possível falha do contrato.

Exceções como Guardas de Contrato — Resposta

Dica

  1. Falso — o compilador só garante o tipo sintático (double), não a validade semântica do valor.
  2. Verdadeiro — é o “erro de silenciar” descrito nesta aula.
  3. Verdadeiro — é a diretriz explícita de responsabilidade.
  4. Verdadeiro — é exatamente a ideia de “exceção como cláusula do contrato”.

Conclusão

O que Aprendemos

  1. Interface = contrato de comportamento, nunca implementação ou estado
  2. default/static/private trazem comportamento sem quebrar retrocompatibilidade
  3. Interface (papel) vs. Classe Abstrata (identidade): a fronteira é o estado
  4. Exceção guarda a regra de negócio que o tipo sozinho não expressa

Próxima aula: Polimorfismo — como o compilador aceita múltiplas formas por trás do mesmo contrato.