Soluções — Polimorfismo, Binding e Generics
Aula 7 — Programação Orientada a Objetos
Dica(Resposta) Teste 1 — O que é Polimorfismo
- ✗ Falso — Polimorfismo exige uma referência de tipo comum (
Pagavel, por exemplo) através da qual o mesmo ponto de chamada produz comportamentos diferentes dependendo do objeto real. Dois métodos de mesmo nome em classes não relacionadas, sem supertipo compartilhado, não passam pelo mecanismo de despacho polimórfico — são apenas nomes coincidentes, sem nenhumforma.metodo()cuja resolução dependa do objeto em runtime. - ✔ Verdadeiro — É o benefício central discutido na aula — o polimorfismo de inclusão permite que o código cliente dependa apenas do supertipo (
Pagavel), reduzindo o acoplamento a implementações concretas e permitindo estender o sistema com novas classes sem alterar o código existente (OCP). - ✔ Verdadeiro — É exatamente o que o polimorfismo de inclusão permite — a mesma assinatura definida no contrato
Pagavelpode ser implementada de formas radicalmente diferentes em cada subtipo, sem que o código cliente precise saber qual delas está rodando. - ✗ Falso — É o oposto: o polimorfismo permite que o código cliente conheça apenas o contrato (
Pagavel/criarCobranca()), sem qualquer conhecimento dos detalhes internos dePix,BoletoouCartao— esse desacoplamento é o ponto central do mecanismo.
Dica(Resposta) Teste 2 — Late Binding (Dynamic Dispatch)
- ✗ Falso — O compilador decide se a chamada compila olhando apenas o tipo declarado da variável (
Pagavel), não as implementações concretas. Se o método não está na interface, a chamada não compila, mesmo que toda implementação real o possua — o compilador não “adivinha” o que as subclasses declaram. - ✔ Verdadeiro — O Late Binding é o que permite essa flexibilidade: o núcleo só precisa conhecer a interface
Processadorem tempo de compilação; qual implementação concreta roda é decidido pela JVM em tempo de execução, olhando o objeto real — o mesmo mecanismo dePagavel/criarCobranca(). - ✗ Falso — É o inverso do que a aula descreve: o compilador (não a JVM) olha o tipo declarado da variável só para checar a existência do método; a JVM, em tempo de execução, decide com base no objeto real alocado na Heap — trocar esses dois papéis é o erro clássico de confundir Static e Dynamic Binding.
- ✔ Verdadeiro — Como o código cliente só depende do tipo declarado (a interface), substituir a implementação concreta injetada não exige nenhuma alteração no código cliente — é o Late Binding sustentando a troca de “motor” mencionada na aula.
Dica(Resposta) Teste 3 — Polimorfismo Universal
- ✔ Verdadeiro — É a essência do Polimorfismo de Inclusão/OCP: o cliente depende só da interface; uma implementação futura, ainda inexistente hoje, já é compatível automaticamente, sem qualquer alteração no código que manipula
Pagavel. - ✗ Falso — É exatamente o oposto — o que caracteriza o Polimorfismo Paramétrico (Generics) é funcionar sobre tipos completamente não relacionados (
Produto,Cliente), sem exigir hierarquia de herança comum; essa é a diferença estrutural em relação ao Polimorfismo de Inclusão. - ✔ Verdadeiro — O Polimorfismo Paramétrico dispensa hierarquia de herança entre os tipos usados como argumento de
T, mas se o próprio algoritmo genérico depende de uma operação específica (comparar), essa exigência precisa vir de algum contrato comum (Comparable<T>) — Generics sem herança entre os dados não elimina a necessidade de contratos quando o algoritmo depende de uma operação. - ✗ Falso — É o oposto do Polimorfismo Universal: o Ad-hoc é resolvido cedo, pelo compilador, sobre um conjunto finito e pré-determinado de tipos (cada versão sobrecarregada precisa ser escrita manualmente) — um tipo novo sempre exige voltar e editar o código, violando o OCP.
Dica(Resposta) Teste 4 — Polimorfismo Ad-hoc
- ✔ Verdadeiro — A sobrecarga é decidida pela assinatura (nome + tipos de parâmetro) declarada, não pelo uso em tempo de execução; um método sobrecarregado nunca chamado ainda é, sintaticamente, um caso válido de sobrecarga — a resolução é inteiramente estática, independente de uso.
- ✗ Falso — A aula chama a sobrecarga de “polimorfismo aparente” justamente porque ela é estática (Early Binding) e não extensível — um tipo novo exige reescrever a classe, violando o OCP.
- ✗ Falso — A resolução de sobrecarga em Java escolhe a assinatura mais específica compatível com o argumento (aqui,
enviar(String email)), não a mais genérica — o compilador prioriza o “melhor encaixe” de tipo, o oposto do que a afirmação propõe. - ✗ Falso — A coerção é resolvida em tempo de compilação, de forma fixa e sintática — não existe decisão em runtime nem dependência do valor da variável; diferente do Late Binding, que de fato decide dinamicamente com base no objeto real.
Dica(Resposta) Teste 5 — Binding Estático vs. Dinâmico
- ✔ Verdadeiro — Como a sobrecarga é resolvida em tempo de compilação (Static Binding), o IDE consegue determinar qual versão roda apenas analisando o código-fonte estaticamente, sem executar o programa — o mesmo não seria possível para Dynamic Binding, cuja decisão depende do objeto real em runtime.
- ✗ Falso —
staticeprivatesão resolvidos via Static Binding — não podem ser sobrescritos polimorficamente; é por isso que a tabela da aula os lista como exemplos de Early Binding, ao lado da sobrecarga. - ✔ Verdadeiro — É a conclusão central da tabela Static vs. Dynamic Binding: o desacoplamento total e a extensibilidade vêm do Dynamic Binding, que permite trocar a implementação real sem alterar o código cliente; o Static Binding, ao contrário, prioriza performance sobre flexibilidade.
- ✔ Verdadeiro — A DI só funciona porque o código cliente depende de um tipo abstrato (interface); a substituição real da implementação injetada é resolvida em runtime pela JVM via Dynamic Binding — o mesmo mecanismo de despacho tardio discutido para
Pagavel.
Dica(Resposta) Teste 6 — O Fim do “Mar de IFs”
- ✗ Falso — A meta-regra da aula é específica sobre
if/switch/instanceofque verificam o tipo de um objeto de negócio para decidir o comportamento; uma checagem de nulidade é uma validação defensiva comum, não um sintoma de polimorfismo mal aproveitado — nem todoifviola o OCP. - ✔ Verdadeiro — É a consequência direta do polimorfismo de inclusão programado contra a interface
Pagavel: o controlador nunca precisa saber quantos ou quais tipos concretos existem — a mesma linhaformaEscolhida.criarCobranca(total)já cobre o tipo novo. - ✗ Falso — É o oposto — precisar de
instanceofpara decidir comportamento por tipo é justamente o sintoma de que o polimorfismo não foi aproveitado; a meta-regra da aula trata isso como um sinal de alerta, não como algo incentivado. - ✔ Verdadeiro — É a mudança central do bloco: em vez de perguntar o tipo e ramificar externamente, o polimorfismo delega a decisão para dentro do próprio objeto (
forma.criarCobranca()), que já sabe como se comportar.
Dica(Resposta) Teste 7 — O Princípio Aberto/Fechado (OCP)
- ✔ Verdadeiro — É a metade “aberta” do OCP: extensão via composição/novas implementações da interface, nunca via reabertura do código que já funciona.
- ✔ Verdadeiro — Se o código do
CheckoutControllerde fato não muda uma linha ao aceitarCripto, a suíte de testes já existente sobre esse código continua válida sem necessidade de retestá-lo — é uma consequência prática direta de “fechado para modificação”. - ✔ Verdadeiro — É o mecanismo técnico por trás do princípio: sem depender de uma interface (
Pagavel), o código cliente teria que conhecer cada classe concreta, e o OCP não seria sustentável. - ✗ Falso — É exatamente o oposto do que o OCP recomenda — o princípio existe para que o código cliente permaneça intocado ao acomodar novos comportamentos, via novas classes que implementam o contrato existente.
Dica(Resposta) Teste 8 — Substitutibilidade
- ✔ Verdadeiro — É a propriedade que sustenta o polimorfismo de inclusão: qualquer
Pagavelconcreto pode ocupar o lugar de outro sem que o código que o manipula perceba a diferença. - ✔ Verdadeiro — É a aplicação concreta da substitutibilidade ao exemplo da aula: o controlador nunca enxerga
Pix/Boleto/Cartaodiretamente, só a interface comum. - ✗ Falso — É o oposto do que a substitutibilidade garante — o controlador chama
criarCobranca()sem nunca precisar saber qual classe concreta implementaPagavelnaquele momento. - ✔ Verdadeiro — É a mesma ideia do OCP aplicada à substitutibilidade: como qualquer
Pagavelé intercambiável, o núcleo do sistema (oCheckoutController) nunca precisa mudar para acomodar um tipo novo.
Dica(Resposta) Teste 9 — O Problema dos Raw Types
- ✔ Verdadeiro — É o caso-limite de ausência total de restrição de tipo: sem Generics,
Objecté o único “contrato” da coleção, aceitando qualquer referência, o que é exatamente o problema que motiva a introdução de Generics. - ✗ Falso — É o oposto — o erro só é detectado tardiamente, no momento em que o item incompatível é efetivamente usado como se fosse do tipo esperado (geralmente via
ClassCastException), não no momento da inserção. - ✔ Verdadeiro — Sem a “etiqueta de tipo” dos Generics, todo item recuperado de uma coleção
Objectprecisa de um cast explícito para o tipo esperado, e esse cast pode falhar em runtime se o item real for de outro tipo. - ✔ Verdadeiro — É a síntese do bloco: o problema central não é a possibilidade do erro em si, mas o fato de ele só se manifestar muito depois da causa real (a inserção), dificultando o diagnóstico.
Dica(Resposta) Teste 10 — Generics como Etiqueta de Segurança
- ✔ Verdadeiro — É o ganho central de Generics: o compilador passa a rejeitar a inserção de um tipo incompatível na própria linha do
add, em vez de deixar o erro estourar depois, comoClassCastException. - ✔ Verdadeiro — Como o compilador já sabe, pela declaração
List<Pagavel>, que todo item é umPagavel, o cast antes exigido na leitura passa a ser inserido automaticamente pelo compilador (elidido no bytecode gerado) — não resta nenhum cast manual explícito no código-fonte. - ✗ Falso — É o oposto do que a aula afirma:
List<Pagavel>diz mais sobre a intenção do código do queListsozinho — a legibilidade aumenta, mesmo que a declaração use mais caracteres. - ✔ Verdadeiro — É a primeira das quatro vantagens práticas listadas na aula: mover a detecção de erro para o tempo de compilação torna o sistema mais robusto, ao custo zero de flexibilidade real.
Dica(Resposta) Teste 11 — Polimorfismo Paramétrico e Identidade
- ✔ Verdadeiro — É a combinação que caracteriza Generics: flexibilidade de um algoritmo único para qualquer tipo, sem abrir mão da checagem de tipos em tempo de compilação — diferente de uma solução baseada em
Object, que sacrificaria essa segurança. - ✔ Verdadeiro — É a distinção estrutural central entre os dois polimorfismos universais: Inclusão depende de uma hierarquia comum (
implements/extends); Paramétrico funciona sobre qualquer tipo, relacionado ou não. - ✔ Verdadeiro — É uma aplicação de Generics a um padrão de projeto comum (o Repositório) não citado literalmente na aula, mas coerente com a “reutilização” listada como uma das quatro vantagens práticas de Generics.
- ✗ Falso — É o oposto do ganho de Generics: o compilador já sabe, pela declaração
Repositorio<T>, o tipo de retorno — não é necessário nenhum cast manual explícito.
Dica(Resposta) Teste 12 — Síntese: Contrato, Polimorfismo e Segurança de Tipo
- ✔ Verdadeiro — É a síntese correta dos três papéis discutidos na aula: cada ferramenta cobre uma camada diferente do mesmo problema — comunicação entre objetos sem acoplamento nem perda de segurança de tipo.
- ✔ Verdadeiro — Um sistema Plug-and-Play precisa aceitar peças novas sem recompilar o núcleo (OCP/polimorfismo) e sem perder segurança de tipo nas coleções que as manipulam (Generics) — a combinação das três ferramentas é o que viabiliza essa propriedade.
- ✗ Falso — Se
ifs de tipo sobre objetos de negócio ainda aparecem em pontos centrais do fluxo, é sinal de que o polimorfismo não foi bem aproveitado nesse ponto — um sistema bem desenhado com as três ferramentas delega essas decisões para dentro dos próprios objetos, não para checagens de tipo no fluxo principal. - ✔ Verdadeiro — É o fio que une os três tópicos da aula: interfaces fixam o contrato em compilação, polimorfismo resolve comportamento sem
ifs frágeis, e Generics move erros de coleção do runtime para a compilação — todas movem risco para mais cedo no ciclo de vida. —