Soluções — Interfaces e o Contrato de Comportamento
Aula 6 — Programação Orientada a Objetos
Dica(Resposta) Teste 1 — Interface como Contrato de Comportamento
- ✔ Verdadeiro — É a definição de interface como Contrato de Comportamento aplicada a um domínio novo:
PassaroeDronenão têm nenhum dado em comum (um bate asas, o outro usa motores), mas a interface só exige que ambos saibamvoar()— o contrato é sobre o que fazem, nunca sobre o que guardam. - ✗ Falso — Métodos abstratos de interface terminam em
;, sem corpo — é exatamente a ausência de implementação que caracteriza a interface como abstração pura. (Métodosdefault/static/private, vistos mais adiante na aula, são a exceção que tem corpo, mas não são obrigatórios.) - ✗ Falso — Java exige que toda classe concreta (não
abstract) implemente todos os métodos abstratos do contrato.@Overridenos dois métodos feitos não compensa o terceiro ausente — o compilador rejeita a classe até que ela implemente o método restante ou seja declaradaabstract. - ✗ Falso —
@Overrideé puramente uma verificação em tempo de compilação — ela avisa o compilador para confirmar que o método realmente sobrescreve algo do contrato. Removê-la não altera em nada o dispatch em tempo de execução; o método continua sendo chamado exatamente da mesma forma.
Dica(Resposta) Teste 2 — Interface como Tipo Puro
- ✔ Verdadeiro — Diferente da herança de classes, que compartilha “DNA” (estrutura, estado, implementação da classe-mãe), a interface funciona como um “crachá”: qualquer classe, de qualquer hierarquia, pode assinar o contrato sem herdar nenhuma estrutura de dados.
- ✔ Verdadeiro — É exatamente o caso de
Pix(lógica de QR Code) eCartaoDeCredito(lógica de criptografia de chip) apresentado na aula: sem nada em comum em termos de dados, ambos são do tipoPagavelpara oCheckoutController. - ✔ Verdadeiro — É a mesma lógica do “crachá” aplicada a um domínio novo:
VeiculoEletricoeGeradornão precisam de nenhuma superclasse em comum — basta que ambos implementemRecarregavelpara serem tratados como o mesmo tipo por quem só precisa recarregá-los. - ✗ Falso — São mecanismos deliberadamente diferentes: herança de classe (
extends) compartilha estrutura/estado/implementação e é limitada a uma única superclasse; implementação de interface (implements) só compartilha um contrato de comportamento e permite múltiplas interfaces por classe.
Dica(Resposta) Teste 3 — Interfaces Modernas: Default, Static, Private
- ✗ Falso — Um novo método abstrato quebra toda classe já existente que implementa a interface, porque nenhuma delas o implementou ainda — todas parariam de compilar até serem atualizadas. É exatamente esse problema de retrocompatibilidade que o método
defaultresolve, fornecendo uma implementação padrão que as classes legadas herdam automaticamente. - ✗ Falso — Interfaces nunca podem ser instanciadas com
newem Java, independentemente de quantos métodos abstratos restam — essa é uma regra da linguagem sobre o que uma interface é (um tipo, não uma classe concreta), não uma consequência de haver ou não métodos pendentes de implementação. - ✔ Verdadeiro — É o papel dos métodos
privatede interface: organizam código interno (como a validação usada porprocessarComLog) sem expor esse detalhe como parte do contrato público, evitando duplicação entre diferentes métodosdefaultda mesma interface. - ✗ Falso — É exatamente o oposto do propósito dos métodos
default: eles permitem evoluir a interface sem quebrar implementações legadas, porque toda classe existente herda automaticamente o comportamento padrão sem precisar de nenhuma alteração manual.
Dica(Resposta) Teste 4 — O Paradoxo do Mutador Cego
- ✔ Verdadeiro — É a definição do Mutador Cego: um método
defaultcomoaplicarJurosorquestra a mudança de estado chamandogetSaldo()/setSaldo()(implementados pela classe concreta), sem que a interface precise guardar nada por conta própria. - ✔ Verdadeiro — É a mesma divisão de trabalho vista em
aplicarJuros/Pix, transposta para um domínio novo: a interface concentra a regra de validação (o “cérebro”), e a classe concreta concentra o armazenamento real da senha (os “músculos”), sem que a interface precise saber onde ou como esse dado é guardado. - ✗ Falso — É o oposto do padrão Mutador Cego:
aplicarJurossó chamagetSaldo()/setSaldo()sem saber se o saldo mora numa variável privada, num banco de dados ou num serviço remoto — a interface age “às cegas”, confiando que a classe concreta implementou esses dois métodos corretamente. - ✗ Falso — O ganho de DRY do método
defaultsó se materializa quando existem múltiplas implementações compartilhando a mesma regra. Com uma única classe implementandoPagavel, não há nada para duplicar — o método poderia estar tanto na interface quanto na própria classe sem qualquer diferença prática de duplicação.
Dica(Resposta) Teste 5 — Interface vs. Classe Abstrata
- ✗ Falso — A tabela da aula já prevê essa exceção: interfaces podem ter atributos
public static final(constantes de tipo, compartilhadas por todas as instâncias, sem estado mutável por objeto). O que permanece proibido é o atributo de instância — algo que cada objeto guardaria com um valor próprio e mutável. - ✔ Verdadeiro — É exatamente a combinação prevista na tabela: herança de classe é única (
extendssó aceita uma classe abstrata), mas implementação de interface é múltipla (implementsaceita várias) — as duas coisas podem coexistir na mesma declaração. - ✗ Falso — É o mapeamento invertido: segundo a tabela da aula, é a classe abstrata que define uma identidade (“o que é” um objeto, com estado compartilhado), e a interface que define um papel/capacidade (“o que faz”, sem nenhum estado). Trocar os dois é a armadilha central deste item.
- ✔ Verdadeiro — É a diretriz de design da aula aplicada a um caso concreto: como há estrutura de dados (
saldo) e comportamento comum a proteger e compartilhar entre as duas contas, a classe abstrata é a ferramenta certa — uma interface não poderia guardarsaldocomo atributo de instância.
Dica(Resposta) Teste 6 — Tipos como Comportamento
- ✔ Verdadeiro — É a tese central do bloco “Tipos são comportamento, não DNA”: ao declarar
Pagavel p, o que importa é quepsabe responder acriarCobranca()/pagamentoConfirmado(), não que tipo de dado ele guarda por dentro. - ✔ Verdadeiro — É a mesma lógica de
Pix/CartaoDeCreditoaplicada a classes reais do Java: apesar de estruturas internas completamente diferentes (lista vs. tabela hash), ambas podem ser tratadas como o mesmo tipoLimpavelpor qualquer código que só precise invocar esse comportamento. - ✗ Falso — O tipo declarado (
Pagavel) é só o contrato mínimo garantido pelo compilador; a classe concreta real por trás da variável (Pix,Boleto,Cartao) só é conhecida em tempo de execução — é justamente essa lacuna que o Polimorfismo, na próxima aula, formaliza. - ✔ Verdadeiro — Declarar o tipo concreto em vez da abstração amarra o
CheckoutControlleraPixespecificamente; seCriptosurgir depois, o controlador precisaria ser reescrito, exatamente o retrabalho que programar paraPagavelevita.
Dica(Resposta) Teste 7 — Os Limites do Sistema de Tipos
- ✔ Verdadeiro — Se
ValorMonetariosó puder ser instanciado com valores válidos (validação no construtor do próprio tipo), então é impossível construir uma instância inválida em primeiro lugar — a checagem deixa de ser uma exceção lançada em tempo de execução e passa a ser garantida estruturalmente antes mesmo de o método ser chamado. - ✗ Falso — O compilador só verifica que o argumento é sintaticamente um
double— um-50.0é umdoubleperfeitamente válido do ponto de vista do compilador. É por isso que a validação semântica (valor <= 0) precisa ser feita explicitamente em tempo de execução, com uma exceção. - ✔ Verdadeiro — A mesma lacuna estrutural se repete em qualquer domínio: o compilador garante o tipo (
int), nunca a validade semântica do valor dentro desse tipo — reservar-3assentos “compila” tão bem quanto reservar3. - ✔ Verdadeiro — É a síntese do papel da exceção nesta aula: ela entra em cena exatamente quando o sistema de tipos já foi satisfeito (o
doublefoi recebido) mas o valor, semanticamente, viola uma regra de negócio que o tipo sozinho não conseguia expressar.
Dica(Resposta) Teste 8 — Fail-Fast e o Erro de Silenciar
- ✗ Falso — É exatamente o oposto do que a aula defende: retornar um valor “de ajuda” para sinalizar erro é descrito como o maior pecado em Orientação a Objetos, porque só empurra o problema para um ponto distante e sem relação óbvia com a causa original.
- ✗ Falso — Fail-Fast significa interromper o fluxo no exato momento da violação, não continuar executando e só deixar um rastro em log. Continuar a execução normalmente após detectar a violação é justamente o “erro de silenciar” disfarçado de log — o problema segue adiante sem ser contido.
- ✔ Verdadeiro — É a consequência prática do “erro de silenciar”: um
nullretornado hoje só vira umNullPointerExceptionquando alguém, mais tarde e em outro lugar do código, tentar usá-lo — sem relação evidente com o método original que causou o problema. - ✔ Verdadeiro — Ao interromper o fluxo imediatamente, a exceção captura o stack trace no ponto exato da causa, preservando a informação necessária para o diagnóstico — o benefício direto de agir Fail-Fast em vez de silenciar o erro.
Dica(Resposta) Teste 9 — Try-Catch como Barreira de Contenção
- ✔ Verdadeiro — É a função de uma barreira de contenção bem posicionada: capturar a exceção lançada por um componente de baixo nível (
Pix,Cartao) e traduzi-la numa resposta controlada para o usuário, em vez de deixar o sistema quebrar de forma bruta. - ✗ Falso — É o inverso da diretriz explícita da aula: componentes de baixo nível devem lançar exceções (ser honestos sobre a falha); são os componentes de alto nível que devem decidir como reagir — capturar e silenciar no próprio nível baixo reintroduziria o “erro de silenciar”.
- ✗ Falso — A diretriz depende de existir alguém no alto nível para capturar e traduzir a exceção; sem esse componente intermediário, a exceção se propaga sem tratamento até o usuário, tipicamente como uma tela de erro bruta (stack trace cru), não uma mensagem tratada.
- ✔ Verdadeiro — É a essência da barreira de contenção: falhas vindas de fatores externos ao controle direto do sistema são contidas no ponto certo, evitando que se propaguem e interrompam o funcionamento do restante da aplicação.
Dica(Resposta) Teste 10 — Novos Contratos: Notificação, Desconto, Logística
- ✔ Verdadeiro — É o mesmo padrão de
Notificavel(o canal deixa de importar) aplicado a um domínio novo: programar contraLogavel, e não contra “arquivo local” especificamente, é o que permite trocar a implementação de destino sem tocar em quem gera os logs. - ✗ Falso — Um
doublesozinho aceita qualquer valor numérico, incluindo5.0(500%) — é exatamente a lacuna que motiva encapsular a regra numa interfaceEstrategiaDescontocom validação própria, em vez de confiar num primitivo isolado. - ✗ Falso — Sem a interface,
Pedidoficaria fisicamente acoplado aTransportadoraCorreios— trocar de transportadora exigiria editarPedidodiretamente, o mesmo problema de acoplamento a classes concretas visto no DIP da Aula 5. A interface é justamente o que evita essa dependência direta. - ✗ Falso — Uma exceção genérica (
Exception) não comunica nada específico sobre o motivo da falha, enquantoCarrierUnavailableExceptionjá indica, pelo próprio nome, a natureza do problema — quanto mais genérica a exceção declarada, menos informativa é a cláusula do contrato para quem precisa tratá-la.
Dica(Resposta) Teste 11 — Exceção como Cláusula de Contrato
- ✔ Verdadeiro — É a mesma função de cláusula de contrato, só que sinalizando uma falha de origem externa (dependência de terceiros) em vez de uma falha de validação de entrada — em ambos os casos, o
throwsavisa formalmente que o método pode não cumprir sua promessa. - ✗ Falso — A “honestidade” da exceção pressupõe um risco real de falha que o método está comunicando ao consumidor do contrato. Declarar uma exceção para uma falha que nunca ocorre de fato é ruído no contrato, não honestidade — é o inverso do propósito descrito na aula.
- ✔ Verdadeiro — É exatamente o papel do alto nível descrito na aula: capturar a exceção lançada pelo baixo nível e decidir como reagir (registrar, notificar, seguir adiante) sem que a falha de um pedido derrube o processamento dos demais — resiliência do sistema como um todo.
- ✗ Falso — É o “erro de silenciar” reaparecendo depois do
catch: capturar a exceção só para descartá-la sem reação nenhuma reproduz o mesmo problema de esconder a falha, só que uma etapa depois. A diretriz da aula é decidir como reagir, não ignorar.
Dica(Resposta) Teste 12 — Síntese: Contratos e Responsabilidade
- ✗ Falso — O princípio de “não saber como” é sobre o tipo de dependência (uma abstração, não uma implementação concreta), não sobre a quantidade de dependências. Mesmo com dez interfaces,
Pedidocontinuaria confiando nos contratos sem conhecer nenhum detalhe de implementação — o número alto poderia levantar uma preocupação de CBO (Aula 5), mas não invalida o encapsulamento garantido pelas interfaces. - ✗ Falso — Retornar
0silenciosamente em vez de lançar uma exceção é exatamente o “erro de silenciar” da aula — quebra a garantia de honestidade que as outras interfaces (Notificavel,ServicoLogistico) mantêm ao declarar explicitamente suas possíveis falhas viathrows. - ✗ Falso — As duas práticas se combinam na mesma aula: a interface define o “o quê” (o contrato de comportamento), e a exceção guarda os limites que o “o quê” não consegue expressar sozinho — juntas, formam o padrão “interface + exceção” repetido em
Notificavel,EstrategiaDescontoeServicoLogistico. - ✔ Verdadeiro — É o resultado prático de programar contra interfaces:
Pedidonunca conhecePix,Boletoou qualquer implementação específica deNotificavel/EstrategiaDesconto/ServicoLogistico— pode-se trocar qualquer uma delas sem tocar emPedido, o mesmo ganho estrutural do DIP na Aula 5, agora viabilizado tecnicamente por interfaces. —