Na classe CentralControle, o método executar_missao() chama métodos como informacoes(), ativar_sistema(), navegar() e mover() sem saber qual tipo específico de veículo está nạ lista. Explique como o polimorfismo garante que cada veículo execute seu comportamento próprio nesses métodos.
Passo 1
O enunciado diz que a classe CentralControle tem um método
que itera sobre uma lista de veículos e, para cada veículo, chama os métodos
,
,
e
sem saber qual é o tipo concreto de cada veículo na lista.
O que é pedido: explicar como o polimorfismo garante que, apesar do CentralControle não conhecer o tipo concreto, cada veículo execute o seu comportamento próprio ao receber essas chamadas.
Informações relevantes dadas ou implicitamente necessárias:
O que é pedido: explicar como o polimorfismo garante que, apesar do CentralControle não conhecer o tipo concreto, cada veículo execute o seu comportamento próprio ao receber essas chamadas.
Informações relevantes dadas ou implicitamente necessárias:
- Existe uma lista contendo objetos de tipos diferentes (vários tipos de veículo).
- CentralControle chama métodos com assinaturas iguais em todos os elementos dessa lista.
- Cada tipo de veículo (por exemplo, Carro, Drone, Submarino) implementa comportamento próprio desses métodos (isso é assumido pelo enunciado).
- A explicação deve mostrar por que as chamadas acabam chamando a implementação certa para cada objeto.
Passo 2
O que é polimorfismo (explicação simples, sem jargões): polimorfismo é a capacidade de um mesmo nome de operação (por exemplo,
) produzir comportamentos diferentes dependendo do tipo do objeto que está recebendo a chamada. Em vez de escrever um monte de “if tipo == Drone then … else if tipo == Carro …” você escreve chamadas iguais e deixa que o próprio objeto responda do jeito certo.
Por que isso importa aqui: CentralControle fala com “um veículo” — não precisa saber se é carro, drone ou submarino — ele só manda a mensagem. O polimorfismo garante que a mensagem seja atendida pela implementação daquele tipo concreto do veículo.
Por que isso importa aqui: CentralControle fala com “um veículo” — não precisa saber se é carro, drone ou submarino — ele só manda a mensagem. O polimorfismo garante que a mensagem seja atendida pela implementação daquele tipo concreto do veículo.
Passo 3
Como isso é organizado no código (estrutura típica):
- Há uma superclasse ou interface comum, por exemplo
, que declara as assinaturas: -
- Cada subclasse (
, , ) sobrescreve (override) essas operações, fornecendo a sua versão concreta.
Exemplo esquemático (pseudo‑código):
```
class Veiculo {
informacoes() { /* vazio ou abstrato / }
ativar_sistema() { / vazio ou abstrato / }
navegar() { / vazio ou abstrato / }
mover() { / vazio ou abstrato */ }
}
class Carro extends Veiculo {
informacoes() { print(“Carro: 4 pneus, tanque…”) }
ativar_sistema() { ligarMotor() }
navegar() { seguirRotaRodovia() }
mover() { acelerar() }
}
class Drone extends Veiculo {
informacoes() { print(“Drone: hélices, bateria…”) }
ativar_sistema() { checarSensores() }
navegar() { calcularAltitude() }
mover() { ajustarHélices() }
}
```
A ideia-chave: todas as classes têm os mesmos nomes de método, mas implementações diferentes.
Passo 4
O que CentralControle faz na prática (loop e chamada):
```
for veiculo in lista_de_veiculos:
veiculo.informacoes()
veiculo.ativar_sistema()
veiculo.navegar()
veiculo.mover()
```
Cada chamada usa a referência do tipo base ( ), mas em tempo de execução o sistema sabe qual é o tipo concreto daquele objeto (Carro, Drone, …). O mecanismo chamado de despacho dinâmico (dynamic dispatch) direciona a chamada para a implementação correta do tipo concreto. Resultado: se
é um
,
executa a versão do
; se for um
, executa a versão do
.
```
for veiculo in lista_de_veiculos:
veiculo.informacoes()
veiculo.ativar_sistema()
veiculo.navegar()
veiculo.mover()
```
Cada chamada usa a referência do tipo base (
Passo 5
Mecanismo técnico por trás (explicação curta, prática):
- Em linguagens com despacho dinâmico (Java, C#, Python, Ruby), métodos de instância já são resolvidos em tempo de execução por padrão.
- Em C++ é preciso marcar métodos como
para habilitar despacho dinâmico. - Em implementações típicas existe uma tabela de funções (vtable) por classe: a chamada via referência base consulta a vtable do objeto concreto e chama o ponteiro correto.
Conseqüência prática: enquanto as assinaturas forem as mesmas e o método for sobreponível, a chamada chega na implementação correta sem nenhum código de escolha manual.
Passo 6
Um passo a mais: contratos e segurança (Liskov e bom design)
- Para que isso funcione bem e sem surpresas, as subclasses devem respeitar o contrato da superclasse: chamadas devem se comportar de maneira compatível (não lançar coisas estranhas, não violar pré-condições). Isso é o princípio de Liskov (substituição).
- Em prova: ao argumentar, mencione que a presença da interface/superclasse e o override são pré‑requisitos práticos para o polimorfismo funcionar corretamente.
Passo 7
Traço de execução passo a passo (exemplo concreto com saída imaginada)
- Suponha lista = [instância de Carro, instância de Drone].
- Iteração 1: veiculo = Carro
- veiculo.informacoes() -> imprime “Carro: 4 pneus…”
- veiculo.ativar_sistema() -> liga motor
- veiculo.navegar() -> segue rota rodoviária
- veiculo.mover() -> acelera
- Iteração 2: veiculo = Drone
- veiculo.informacoes() -> imprime “Drone: hélices…”
- veiculo.ativar_sistema() -> checa sensores
- veiculo.navegar() -> calcula altitude
- veiculo.mover() -> ajusta hélices
Observe: o código do CentralControle não mudou entre as iterações; são as implementações dos objetos que determinam o comportamento real.
Passo 8
Erros comuns que quebram o polimorfismo (o que checar se algo não estiver funcionando)
- Métodos declarados como estáticos ou fechados (non-virtual em C++) não são polimórficos.
- Fazer casts e usar instanceof/if‑type em excesso é sinal de que não se está aproveitando polimorfismo — isso leva a código frágil.
- Esquecer de sobrescrever um método (ou escrever assinatura diferente) faz com que a implementação da superclasse seja chamada em vez da esperada.
- Garantir que a lista/coleção guarde referências do tipo base (por exemplo,
), senão não há chamada uniforme.
Passo 9
Como você deve responder na prova (checklist simples)
- Diga que CentralControle usa referências do tipo base e chama métodos comuns.
- Explique que subclasses fornecem implementações próprias (override).
- Cite despacho dinâmico / binding em tempo de execução que escolhe a implementação correta.
- Mencione precauções: métodos devem ser sobreponíveis (virtual/override) e as subclasses devem cumprir o contrato da superclasse.
- Se pedir, exemplifique com um minitrecho de código ou um traço de execução como no Passo 7.
Resposta
Quando CentralControle chama
,
,
e
sobre referências do tipo base (por exemplo
), o polimorfismo faz com que o despacho dinâmico em tempo de execução direcione cada chamada para a implementação sobrescrita no tipo concreto do objeto (Carro, Drone, Submarino etc.), garantindo assim que cada veículo execute seu comportamento próprio.