4. Polimorfismo

  • Crie uma classe CentralControle que possui uma lista de veículos autônomos.
  • Implemente um método executarMissao() que percorre a lista e chama polimorficamente os métodos informacoes(), ativarSisțema(), mover() e navegar().
Além disso,
✓ Adicione um método calcularEficiência() em Veiculo como abstrato.
✓ Cada classe concreta deve implementar esse método com uma lógica diferente (ex.: carro retorna eficiência baseada em consumo de combustível, drone baseada em bateria, ônibus basȩada em número de passageiros).
✓ No exceutarMissão(), exiba também a eficiência calculada de cada veiculo

Passo 1

O enunciado pede que eu crie um sistema com polimorfismo que envolva:
  • Uma classe chamada CentralControle que possui uma lista de veículos autônomos.
  • Um método executarMissao() em CentralControle que percorre essa lista e, para cada veículo, chama polimorficamente os métodos informacoes(), ativarSistema(), mover() e navegar().
  • Em Veiculo deve ser adicionado o método calcularEficiência() como abstrato.
  • Cada classe concreta (por exemplo Carro, Drone, Onibus) deve implementar calcularEficiência() com lógica diferente (ex.: carro → eficiência baseada em consumo de combustível; drone → baseada em bateria; ônibus → baseada em número de passageiros).
  • No executarMissao() também deve ser exibida a eficiência calculada de cada veículo.
Informações relevantes fornecidas:
  • Métodos obrigatórios a serem chamados durante a missão: informacoes(), ativarSistema(), mover(), navegar().
  • Deve existir calcularEficiência() em Veiculo como método abstrato.
  • Cada subclasse deve implementar calcularEficiência() com lógica distinta.
  • executarMissao() deve percorrer a lista e exibir a eficiência de cada veículo.

Passo 2

Decisão sobre linguagem e abordagem (sem resolver ainda): vou usar Java para implementar esse exemplo porque Java é uma linguagem orientada a objetos bem clara para explicar classes abstratas, herança e polimorfismo — e é muito usada em exercícios acadêmicos de POO. A estrutura que vou criar é:
  • abstract class Veiculo com métodos abstratos (incluindo calcularEficiencia()).
  • Subclasses concretas: Carro, Drone, Onibus que implementam os métodos abstratos e cada uma com sua lógica de eficiência.
  • CentralControle com List<Veiculo> e método executarMissao() que chama polimorficamente os métodos pedidos e imprime a eficiência.
Vou implementar também um Main de exemplo que instancia alguns veículos, adiciona ao CentralControle e chama executarMissao() para mostrar o comportamento.

Passo 3

Conceitos-chave que vou usar (explicação didática curta para a prova):
  • Classe abstrata: uma classe que não pode ser instanciada e pode conter métodos abstratos (assinaturas sem implementação). Serve para definir uma interface comum e forçar subclasses a implementar detalhes.
  • Método abstrato: declarado na classe abstrata; obriga as subclasses a fornecer a implementação.
  • Polimorfismo dinâmico (dispatch dinâmico): quando se tem uma referência do tipo da superclasse (Veiculo v = new Carro(...);) e se chama v.mover(), a implementação que será executada é a da classe concreta (Carro) em tempo de execução. Isso é essencial para executarMissao() — ele só precisa conhecer Veiculo.
  • Upcasting: atribuir objeto concreto para uma referência do tipo abstrato/superclasse; isso permite colocar diferentes tipos na mesma lista.
  • Boas práticas: cada subclasse implementa informacoes() mostrando o que ela é e quais dados relevantes ela tem — isso ajuda a saber o que significa a eficiência que será exibida.

Passo 4

Projeto da classe base Veiculo (o que ela deve conter e por quê):
  • Atributo comum: id (identificador), pode ter outros campos dependendo do tipo.
  • Métodos (podem ser abstratos ou com comportamento padrão):
    • informacoes() — mostra dados do veículo (pode ser abstrato para forçar implementação específica).
    • ativarSistema() — simula a ativação dos sistemas.
    • mover() — ação de mover.
    • navegar() — ação de navegação/autonomia.
    • calcularEficiencia() — obrigatório e abstrato (retorna double).
  • Vou tornar os métodos citados abstratos (exceto o construtor), pois cada classe concreta pode querer um comportamento próprio de exibição/ativação/movimento/navegação.

Passo 5

Lógica de eficiência que vou usar (explicando como calcular — útil para a prova):
  • Carro:
    • Atributo: consumoLitrosPor100km (quanto o carro consome em litros a cada 100 km).
    • Eficiência: kmPorLitro = 100 / consumoLitrosPor100km. Esse número fica fácil de interpretar (quanta distância o carro percorre por litro).
  • Drone:
    • Atributos: autonomiaMinutosPorCarga (minutos de voo com bateria cheia) e porcentagemBateria (nível atual, 0 a 100).
    • Eficiência: minutosRestantes = autonomiaMinutosPorCarga * (porcentagemBateria / 100). Interpretação: tempo de voo restante com a carga atual.
  • Ônibus:
    • Atributos: consumoLitrosPor100km e passageiros.
    • Eficiência: passengerKmPerLiter = passageiros * (100 / consumoLitrosPor100km). Interpretação: quantos “passageiro·quilômetros” o ônibus entrega por litro (é uma métrica comum para transporte coletivo: quantos passageiros transportados por distância por unidade de combustível).
Observação importante (para a prova): cada classe pode escolher unidades diferentes para a “eficiência”, o que é aceitável — o que importa é que cada implementação faça sentido na métrica escolhida. Por isso, nas informacoes() de cada classe vou explicar qual unidade aquela eficiência representa.

Passo 6

Implementação (explicada passo a passo). Primeiro a estrutura da classe Veiculo (em Java) e por que cada parte está ali:
  • abstract class Veiculo com protected String id;
  • Construtor que recebe id.
  • Assinaturas abstratas:
    • public abstract void informacoes();
    • public abstract void ativarSistema();
    • public abstract void mover();
    • public abstract void navegar();
    • public abstract double calcularEficiencia();
Explicação didática de cada método:
  • informacoes(): cada veículo mostra seu tipo e atributos (ajuda a entender a eficiência).
  • ativarSistema(): simula iniciar sensores, ligar motores, etc.
  • mover() e navegar(): representam comportamentos distintos (mover: deslocamento; navegar: planejar/seguir rota).
  • calcularEficiencia(): retorna número que traduz a eficiência segundo lógica específica da subclasse.

Passo 7

Implementações das subclasses com exemplos concretos:
  • Carro:
    • Campos: consumoLitrosPor100km.
    • Implementa informacoes() mostrando id e consumo.
    • calcularEficiencia() retorna 100.0 / consumoLitrosPor100km (km por litro).
  • Drone:
    • Campos: autonomiaMinutosPorCarga, porcentagemBateria.
    • calcularEficiencia() retorna autonomiaMinutosPorCarga * (porcentagemBateria / 100.0) (minutos restantes).
  • Onibus:
    • Campos: consumoLitrosPor100km, passageiros.
    • calcularEficiencia() retorna passageiros * (100.0 / consumoLitrosPor100km) (passenger-km por litro).
Em cada método ativarSistema(), mover(), navegar() vou colocar mensagens simples para demonstrar comportamento (ex.: “Sensores do drone inicializados”, “Ônibus iniciando rota”).

Passo 8

Classe CentralControle e o método executarMissao() (explicação prática):
  • CentralControle tem private List<Veiculo> veiculos = new ArrayList<>();
  • Método adicionarVeiculo(Veiculo v) para popular a lista.
  • Método executarMissao():
    • Percorre veiculos (for-each).
    • Para cada Veiculo v chama, nesta ordem:
      1. v.informacoes();
      2. v.ativarSistema();
      3. v.mover();
      4. v.navegar();
      5. double eficiencia = v.calcularEficiencia();
      6. Imprime a eficiência (formatada).
  • Observação didática: o código em executarMissao() conhece apenas o tipo Veiculo, não as classes concretas; ainda assim, em tempo de execução cada chamada é resolvida para a implementação correta — isso é polimorfismo.

Passo 9

Exemplo completo de uso (main) e saída esperada:
  • No main, instanciar:
    • Carro c1 = new Carro("Carro-01", 8.5); // 8,5 L/100km
    • Drone d1 = new Drone("Drone-Alpha", 30.0, 75.0); // 30 min por carga, 75% bateria
    • Onibus o1 = new Onibus("Onibus-100", 40.0, 50); // 40 L/100km, 50 passageiros
  • Adicionar ao CentralControle e chamar executarMissao().
  • Saída esperada (exemplo):
    • Informações do veículo
    • Mensagens de ativação, movimento, navegação
    • “Eficiência calculada: 11,76” (por exemplo para carro; aqui 100/8.5 ≈ 11.76 km/L)
    • Para drone: “Eficiência calculada: 22,50” (minutos restantes: 30 * 0,75 = 22.5)
    • Para ônibus: “Eficiência calculada: 125,00” (passenger-km/L: 50 * (100/40) = 125)

Passo 10

Dicas rápidas para a prova (resumidas e úteis):
  • Lembre-se: ao chamar métodos em uma referência do tipo da superclasse, a JVM (ou mecanismo da linguagem) escolhe a implementação da subclasse em tempo de execução.
  • Método abstrato obriga implementação nas subclasses concretas — útil para garantir que calcularEficiencia() exista para todo veículo.
  • Pense nas unidades de eficiência e informe-as em informacoes() para evitar confusão.
  • Em provas, explique a métrica que você escolheu quando pedir para “calcular eficiência”; mostrar a fórmula ajuda a justificar a implementação.

Resposta

Abaixo está um exemplo completo em Java que implementa tudo o que foi pedido. Copie e cole num arquivo Main.java (ou vários arquivos conforme preferir) e rode para ver o comportamento.
import java.util.ArrayList;
import java.util.List;

// Classe abstrata Veiculo
abstract class Veiculo {
    protected String id;

    public Veiculo(String id) {
        this.id = id;
    }

    public abstract void informacoes();
    public abstract void ativarSistema();
    public abstract void mover();
    public abstract void navegar();
    public abstract double calcularEficiencia();
}

// Carro: eficiência baseada em consumo (km por litro)
class Carro extends Veiculo {
    private double consumoLitrosPor100km; // ex.: 8.5 L/100km

    public Carro(String id, double consumoLitrosPor100km) {
        super(id);
        this.consumoLitrosPor100km = consumoLitrosPor100km;
    }

    @Override
    public void informacoes() {
        System.out.println("=== Carro: " + id + " ===");
        System.out.println("Consumo: " + consumoLitrosPor100km + " L/100km");
        System.out.println("Eficiência medida em km/L (quanto maior, melhor).");
    }

    @Override
    public void ativarSistema() {
        System.out.println("Carro " + id + ": ligar ignição e sistemas eletrônicos.");
    }

    @Override
    public void mover() {
        System.out.println("Carro " + id + ": mover-se pela via.");
    }

    @Override
    public void navegar() {
        System.out.println("Carro " + id + ": navegando rota GPS.");
    }

    @Override
    public double calcularEficiencia() {
        // km por litro = 100 / (L por 100km)
        return 100.0 / consumoLitrosPor100km;
    }
}

// Drone: eficiência baseada em bateria (minutos restantes)
class Drone extends Veiculo {
    private double autonomiaMinutosPorCarga; // minutos com bateria 100%
    private double porcentagemBateria; // 0..100

    public Drone(String id, double autonomiaMinutosPorCarga, double porcentagemBateria) {
        super(id);
        this.autonomiaMinutosPorCarga = autonomiaMinutosPorCarga;
        this.porcentagemBateria = porcentagemBateria;
    }

    @Override
    public void informacoes() {
        System.out.println("=== Drone: " + id + " ===");
        System.out.println("Autonomia por carga: " + autonomiaMinutosPorCarga + " minutos");
        System.out.println("Bateria atual: " + porcentagemBateria + " %");
        System.out.println("Eficiência medida em minutos de voo restantes.");
    }

    @Override
    public void ativarSistema() {
        System.out.println("Drone " + id + ": inicializando sensores e hélices.");
    }

    @Override
    public void mover() {
        System.out.println("Drone " + id + ": decolando e deslocando-se.");
    }

    @Override
    public void navegar() {
        System.out.println("Drone " + id + ": seguindo rota de navegação autônoma.");
    }

    @Override
    public double calcularEficiencia() {
        // minutos restantes = autonomia * (porcentagem / 100)
        return autonomiaMinutosPorCarga * (porcentagemBateria / 100.0);
    }
}

// Onibus: eficiência baseada em passageiros (passenger-km por litro)
class Onibus extends Veiculo {
    private double consumoLitrosPor100km; // L/100km
    private int passageiros;

    public Onibus(String id, double consumoLitrosPor100km, int passageiros) {
        super(id);
        this.consumoLitrosPor100km = consumoLitrosPor100km;
        this.passageiros = passageiros;
    }

    @Override
    public void informacoes() {
        System.out.println("=== Ônibus: " + id + " ===");
        System.out.println("Consumo: " + consumoLitrosPor100km + " L/100km");
        System.out.println("Passageiros a bordo: " + passageiros);
        System.out.println("Eficiência medida em passenger-km por litro (quanto maior, melhor).");
    }

    @Override
    public void ativarSistema() {
        System.out.println("Ônibus " + id + ": verificando sistemas e doors.");
    }

    @Override
    public void mover() {
        System.out.println("Ônibus " + id + ": iniciando deslocamento pela rota.");
    }

    @Override
    public void navegar() {
        System.out.println("Ônibus " + id + ": seguindo rota programada.");
    }

    @Override
    public double calcularEficiencia() {
        // passenger-km per liter = passageiros * (100 / consumo L/100km)
        return passageiros * (100.0 / consumoLitrosPor100km);
    }
}

// CentralControle que guarda a lista de veículos e executa missões
class CentralControle {
    private List<Veiculo> veiculos = new ArrayList<>();

    public void adicionarVeiculo(Veiculo v) {
        veiculos.add(v);
    }

    public void executarMissao() {
        for (Veiculo v : veiculos) {
            v.informacoes();               // polimórfico
            v.ativarSistema();             // polimórfico
            v.mover();                     // polimórfico
            v.navegar();                   // polimórfico
            double eficiencia = v.calcularEficiencia(); // polimórfico
            System.out.printf("Eficiência calculada: %.2f%n", eficiencia);
            System.out.println(); // linha em branco entre veículos
        }
    }
}

// Classe Main com exemplo de uso
public class Main {
    public static void main(String[] args) {
        CentralControle central = new CentralControle();

        Carro c1 = new Carro("Carro-01", 8.5);           // 8.5 L/100km -> ~11.76 km/L
        Drone d1 = new Drone("Drone-Alpha", 30.0, 75.0); // 30 minutos por carga, 75% bateria -> 22.5 min
        Onibus o1 = new Onibus("Onibus-100", 40.0, 50);   // 40 L/100km, 50 passageiros -> 125 passenger-km/L

        central.adicionarVeiculo(c1);
        central.adicionarVeiculo(d1);
        central.adicionarVeiculo(o1);

        central.executarMissao();
    }
}
Boa! Esse código mostra claramente polimorfismo: CentralControle chama os mesmos métodos em referências do tipo Veiculo e cada classe concreta executa seu comportamento próprio e calcula sua própria eficiência. Se quiser, posso adaptar o exemplo para outra linguagem (Python, C#) ou adicionar mais métricas (por exemplo, normalizar todas as eficiências para uma unidade comum). Vai com calma — isso dá certo na prova se você explicar a métrica escolhida e lembrar que o polimorfismo resolve as chamadas em tempo de execução.

Exercícios relacionados