Exercícios — Polimorfismo, Binding e Generics
Aula 7 — Programação Orientada a Objetos
Marcos M. Raimundo — Instituto de Computação, UNICAMP
Questões discursivas
Defina Static (Early) Binding e Dynamic (Late) Binding, explicitando em qual momento do ciclo de vida do software cada um atua e qual agente (compilador ou JVM) toma a decisão. Por que o desacoplamento em Orientação a Objetos depende criticamente do Late Binding?
Um desenvolvedor júnior escreve um método
efetuarCobrancaque inspeciona umaString tipoPagamentonuma cadeia deif/elsepara dispararPixServiceouBoletoService. Critique esse design com base no Princípio Aberto/Fechado e mostre, em texto, como o Polimorfismo de Inclusão elimina esse sintoma.Explique o cenário de “Heterogeneidade Acidental” numa lista sem Generics num sistema de checkout, e como
List<Pagavel>protege o usuário final de umClassCastExceptionem produção.
Questões de Verdadeiro/Falso
Cada bloco de 4 itens trata do mesmo tema. A questão só é considerada correta se todos os 4 itens forem julgados corretamente (deixar em branco tem penalidade de 20% da nota da questão).
- □ Duas classes que implementam métodos com o mesmo nome, mas sem relação de herança ou interface comum entre elas, já caracterizam polimorfismo, pois cada uma se comporta de forma diferente.
- □ O objetivo prático do polimorfismo é reduzir o acoplamento e aumentar a extensibilidade do sistema.
- □
pagamentoConfirmado()pode se comportar como consulta de API noPixe como verificação de data noBoleto. - □ O código que chama a operação precisa conhecer os detalhes de implementação de quem a executa.
- □ Se a interface
Pagavelnão declarassecriarCobranca(), mas todas as classes que a implementam (Pix,Cartao) declarassem esse método por conta própria, a chamadaforma.criarCobranca(total)ainda compilaria normalmente. - □ Num sistema de plugins em que cada plugin implementa a interface comum
Processador, é possível adicionar um plugin novo, compilado separadamente, sem recompilar o núcleo do sistema — graças ao mesmo mecanismo que decide, emPagavel, qualcriarCobranca()roda. - □ A JVM decide olhando o tipo declarado da variável, não o objeto real na memória.
- □ Late Binding é o que permite trocar a implementação injetada sem que o código cliente perceba.
- □ Uma nova classe que implemente
Pagaveldepois que o sistema já estiver em produção pode ser usada em qualquer lugar que espere umPagavel, sem exigir recompilação do código cliente existente. - □ O Polimorfismo Paramétrico exige que todos os tipos usados pertençam à mesma hierarquia de herança.
- □ Um método genérico
ordenar(List<T> lista)que funciona tanto paraList<Produto>quanto paraList<Cliente>deixaria de compilar seProdutoeClientenão implementassem uma interfaceComparableem comum. - □ Um sistema que usa apenas Polimorfismo Ad-hoc (sobrecarga e coerção) já suporta, em princípio, um número infinito de tipos diferentes sem precisar editar código existente.
- □ Um método
enviar(String email)e um métodoenviar(int codigo)na mesma classeNotificadorconfiguram sobrecarga, mesmo que um deles nunca seja chamado em nenhum lugar do sistema. - □ A sobrecarga é considerada um polimorfismo verdadeiramente dinâmico e extensível.
- □ Se dois métodos sobrecarregados
enviar(String email)eenviar(Object dado)puderem ambos aceitar um argumento do tipoString, o compilador escolhe sempre a versão mais genérica (Object), para reduzir o número de conversões implícitas. - □ A coerção de
intparadoublenuma expressão aritmética pode ser desativada em tempo de execução dependendo do valor concreto da variável, da mesma forma que o Late Binding decide em runtime qual método roda.
- □ Um IDE que sugere automaticamente, enquanto o código é digitado, qual método
enviar()sobrecarregado será chamado, está inspecionando o comportamento do Static Binding, não do Dynamic Binding. - □ Métodos
staticeprivateem Java são resolvidos via Dynamic Binding. - □ O Dynamic Binding é o que sustenta o desacoplamento e a extensibilidade típicos da Orientação a Objetos.
- □ A Injeção de Dependência se apoia no Dynamic Binding para trocar implementações sem alterar o código cliente.
- □ Uma cadeia de
if/elseque verifica, dentro de um método de log genérico, se o parâmetro énullantes de gravá-lo, é um sintoma da mesma violação de OCP que a cadeia deif/elsesobre tipos de pagamento. - □ Com polimorfismo, adicionar um novo meio de pagamento não exige alterar o código do controlador.
- □ O uso de
instanceofpara decidir o comportamento com base no tipo concreto é incentivado pelo polimorfismo. - □ Delegar a decisão para o próprio objeto substitui a necessidade de perguntar “qual é o seu tipo?”.
- □ Um sistema está “aberto para extensão” quando comportamentos novos entram via novas classes, não via edição das antigas.
- □ Estar “fechado para modificação” significa que o código cliente não precisa ser retestado ao aceitar um novo ator.
- □ Programar para interfaces, em vez de classes concretas, é o mecanismo que viabiliza o cumprimento do OCP.
- □ O OCP recomenda revisar e reescrever o código cliente a cada novo comportamento adicionado ao sistema.
- □ A substitutibilidade é a capacidade de trocar implementações concretas por uma abstração comum sem impacto perceptível.
- □
CheckoutControllertrataPix,BoletoeCartaode forma uniforme através da “lente” do tipoPagavel. - □ Para usar
criarCobranca(), o controlador precisa saber qual classe concreta está por trás da referência. - □ A substitutibilidade é o que permite ao sistema aceitar novos meios de pagamento sem alterar o núcleo.
- □ Sem Generics, uma coleção Java podia armazenar referências genéricas do tipo
Object. - □ O risco de inserir um objeto incompatível numa lista sem Generics é detectado imediatamente pelo compilador.
- □ Recuperar dados de uma coleção não parametrizada exigia casting manual, sujeito a
ClassCastException. - □ A detecção tardia de um erro de tipo é o principal risco prático dos raw types.
- □
List<Pagavel>desloca a detecção de erros de tipo do tempo de execução para o tempo de compilação. - □ Generics elimina a necessidade de casting manual na leitura de itens de uma coleção parametrizada.
- □ Generics reduz a legibilidade do código, pois exige mais caracteres na declaração de tipos.
- □ Proibir a inserção de tipos incompatíveis é uma das formas como Generics aumenta a robustez do sistema.
- □ O Polimorfismo Paramétrico usa variáveis de tipo (como
<T>) mantendo a segurança de tipos estáticos. - □ Diferente do Polimorfismo de Inclusão, o Paramétrico não exige que os tipos usados pertençam à mesma árvore de herança.
- □ Um
Repositorio<T>genérico centraliza a lógica de infraestrutura sem duplicar código para cada entidade. - □ Recuperar um item de um
Repositorio<T>obriga o desenvolvedor a fazer um cast manual para o tipo concreto.
- □ Interfaces definem o contrato; Polimorfismo de Inclusão o torna substituível; Generics protege coleções desses contratos.
- □ O uso conjunto de interfaces, polimorfismo e Generics é o que sustenta sistemas verdadeiramente Plug-and-Play.
- □ Um sistema bem desenhado com essas três ferramentas ainda pode exigir
ifs de tipo em pontos centrais do fluxo. - □ A meta comum às três ferramentas é mover decisões e erros para o momento mais cedo e mais seguro possível do ciclo de vida do software.