Menu
Coddy logo textTech

Serviço de Aluguel de Veículos

Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 87 de 87.

Para este desafio final, você construirá um sistema de Serviço de Aluguel de Veículos que reúne todos os conceitos de POO que você dominou ao longo deste curso.

Seu sistema deve modelar uma frota de diferentes tipos de veículos. Considere uma classe base Vehicle com propriedades comuns como placa, marca e valor da diária de aluguel. Subclasses como Car, Motorcycle e Truck podem estender isso com atributos específicos como número de assentos, cilindrada ou capacidade de carga.

Interfaces podem definir comportamentos de aluguel: uma interface Rentable pode declarar métodos como rent(), returnVehicle() e calculateCost(int days). Diferentes tipos de veículos podem implementar estratégias de precificação de forma diferente, tornando este um caso de uso perfeito para o polimorfismo.

Pense em como uma classe RentalAgency gerencia a frota usando composição.

Exceções personalizadas como VehicleNotAvailableException podem lidar com casos extremos.

Você pode aplicar o padrão Factory para criar veículos ou usar enums para categorias de veículos e status de aluguel.

Este desafio testa sua habilidade de projetar um sistema OOP completo e bem estruturado. Boa sorte!

challenge icon

Desafio

Fácil

Vamos construir um Serviço de Aluguel de Veículos completo que reúne tudo o que você aprendeu sobre POO! Você criará um sistema que gerencia uma frota de diferentes tipos de veículos, lida com aluguéis com a validação adequada e usa um padrão de fábrica para criar veículos.

Você organizará seu código em sete arquivos:

  • RentalStatus.java: Crie um enum representando o status de aluguel de um veículo. Inclua os valores AVAILABLE, RENTED e MAINTENANCE. Adicione um campo privado description (String), um construtor e um getter. AVAILABLE deve ter a descrição "ready to rent", RENTED deve ter "currently in use" e MAINTENANCE deve ter "under service".
  • VehicleNotAvailableException.java: Crie uma exceção personalizada que estende Exception. O construtor deve aceitar uma placa (license plate) e criar uma mensagem no formato Vehicle not available: [licensePlate].
  • Rentable.java: Crie uma interface definindo as operações de aluguel. Declare os métodos rent() retornando um boolean, returnVehicle() retornando um boolean e calculateCost(int days) retornando um double.
  • Vehicle.java: Crie uma classe base abstrata para todos os veículos. Inclua campos privados para licensePlate (String), brand (String), dailyRate (double) e status (RentalStatus, inicializado como AVAILABLE). O construtor recebe licensePlate, brand e dailyRate. Inclua os getters apropriados e um setter para status. Declare um método abstrato getVehicleType() retornando uma String. Implemente um método getDetails() que retorna "[licensePlate] [brand] ([vehicleType]) - $[dailyRate]/day - [status description]" com dailyRate formatado para 2 casas decimais.
  • Car.java: Crie uma classe estendendo Vehicle e implementando Rentable. Adicione um campo privado seats (int). O construtor recebe licensePlate, brand, dailyRate e seats. Implemente getVehicleType() para retornar "Car". Para rent(), se o status for AVAILABLE, defina-o como RENTED e retorne true; caso contrário, retorne false. Para returnVehicle(), se o status for RENTED, defina-o como AVAILABLE e retorne true; caso contrário, retorne false. Para calculateCost(int days), retorne dailyRate vezes days.
  • Motorcycle.java: Crie uma classe estendendo Vehicle e implementando Rentable. Adicione um campo privado engineCC (int). O construtor recebe licensePlate, brand, dailyRate e engineCC. Implemente getVehicleType() para retornar "Motorcycle". Implemente os métodos de Rentable da mesma forma que Car, mas calculateCost() deve aplicar um desconto de 10% (multiplicar por 0.9).
  • RentalAgency.java: Crie uma classe que gerencia a frota de veículos usando um ArrayList. Inclua os métodos:
    • addVehicle(Vehicle vehicle) - adiciona um veículo à frota
    • findVehicle(String licensePlate) - retorna o Vehicle ou null
    • rentVehicle(String licensePlate, int days) - encontra o veículo, tenta alugá-lo (fazendo o cast para Rentable) e retorna o custo do aluguel. Lance VehicleNotAvailableException se o veículo não for encontrado ou se rent() retornar false
    • returnVehicle(String licensePlate) - encontra e devolve o veículo, retornando true em caso de sucesso
    • getAvailableVehicles() - retorna um ArrayList de veículos com status AVAILABLE
  • Main.java: Construa seu serviço de aluguel! Você receberá uma string de comandos separados por vírgula:
    • ADD_CAR:licensePlate:brand:dailyRate:seats
    • ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC
    • RENT:licensePlate:days
    • RETURN:licensePlate
    • AVAILABLE

    Processe cada comando e imprima:

    • ADD_CAR/ADD_MOTORCYCLE: Added: [brand] ([vehicleType])
    • RENT: Rented [licensePlate] for [days] days - Total: $[cost] (custo com 2 decimais), ou Error: [exception message]
    • RETURN: Returned: [licensePlate] ou Return failed: [licensePlate]
    • AVAILABLE: Imprima Available vehicles: seguido pelos detalhes de cada veículo disponível em linhas separadas

    Após todos os comandos, imprima --- Fleet Summary --- seguido pelos detalhes de cada veículo.

Você receberá uma entrada: a string de comandos separados por vírgula.

Por exemplo, com a entrada ADD_CAR:ABC-123:Toyota:50.00:5,ADD_MOTORCYCLE:XYZ-789:Honda:40.00:600,RENT:ABC-123:3,RENT:ABC-123:2,AVAILABLE,RETURN:ABC-123, sua saída seria:

Added: Toyota (Car)
Added: Honda (Motorcycle)
Rented ABC-123 for 3 days - Total: $150.00
Error: Vehicle not available: ABC-123
Available vehicles:
XYZ-789 Honda (Motorcycle) - $40.00/day - ready to rent
Returned: ABC-123
--- Fleet Summary ---
ABC-123 Toyota (Car) - $50.00/day - ready to rent
XYZ-789 Honda (Motorcycle) - $40.00/day - ready to rent

Este desafio combina herança (hierarquia Vehicle), interfaces (Rentable), enums (RentalStatus), exceções personalizadas, polimorfismo (tratando diferentes tipos de veículos uniformemente) e composição (RentalAgency gerenciando veículos) em um sistema completo de serviço de aluguel!

Folha de consulta

Este desafio final combina múltiplos conceitos de POO em um sistema completo. Aqui estão os principais padrões e técnicas:

Enums com Campos

Enums podem ter campos, construtores e métodos:

public enum RentalStatus {
    AVAILABLE("ready to rent"),
    RENTED("currently in use");
    
    private String description;
    
    private RentalStatus(String description) {
        this.description = description;
    }
    
    public String getDescription() {
        return description;
    }
}

Exceções Personalizadas

Crie exceções específicas do domínio estendendo Exception:

public class VehicleNotAvailableException extends Exception {
    public VehicleNotAvailableException(String licensePlate) {
        super("Vehicle not available: " + licensePlate);
    }
}

Classes Abstratas com Interfaces

Combine classes abstratas para implementação compartilhada com interfaces para contratos de comportamento:

public abstract class Vehicle {
    private String licensePlate;
    private RentalStatus status;
    
    public abstract String getVehicleType();
    
    public String getDetails() {
        return licensePlate + " " + getVehicleType() + " - " + status.getDescription();
    }
}

public interface Rentable {
    boolean rent();
    boolean returnVehicle();
    double calculateCost(int days);
}

public class Car extends Vehicle implements Rentable {
    public boolean rent() {
        if (getStatus() == RentalStatus.AVAILABLE) {
            setStatus(RentalStatus.RENTED);
            return true;
        }
        return false;
    }
}

Composição para Gerenciamento

Use composição para gerenciar coleções de objetos:

public class RentalAgency {
    private ArrayList<Vehicle> fleet = new ArrayList<>();
    
    public void addVehicle(Vehicle vehicle) {
        fleet.add(vehicle);
    }
    
    public double rentVehicle(String licensePlate, int days) throws VehicleNotAvailableException {
        Vehicle vehicle = findVehicle(licensePlate);
        if (vehicle == null) {
            throw new VehicleNotAvailableException(licensePlate);
        }
        Rentable rentable = (Rentable) vehicle;
        if (!rentable.rent()) {
            throw new VehicleNotAvailableException(licensePlate);
        }
        return rentable.calculateCost(days);
    }
}

Polimorfismo em Ação

Diferentes subclasses podem implementar métodos de interface de forma distinta:

// Car: standard pricing
public double calculateCost(int days) {
    return dailyRate * days;
}

// Motorcycle: discounted pricing
public double calculateCost(int days) {
    return dailyRate * days * 0.9;
}

Experimente você mesmo

import java.util.Scanner;
import java.util.ArrayList;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        
        // TODO: Criar uma instância de RentalAgency
        
        // TODO: Dividir a entrada por vírgula para obter comandos individuais
        
        // TODO: Processar cada comando:
        // ADD_CAR:licensePlate:brand:dailyRate:seats -> imprimir "Added: [brand] ([vehicleType])"
        // ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC -> imprimir "Added: [brand] ([vehicleType])"
        // RENT:licensePlate:days -> imprimir "Rented [licensePlate] for [days] days - Total: $[cost]" (2 casas decimais)
        //                           ou "Error: [exception message]" se uma exceção for lançada
        // RETURN:licensePlate -> imprimir "Returned: [licensePlate]" ou "Return failed: [licensePlate]"
        // AVAILABLE -> imprimir "Available vehicles:" seguido pelos detalhes de cada veículo disponível
        
        // TODO: Após todos os comandos, imprimir "--- Fleet Summary ---"
        // seguido pelos detalhes de cada veículo
    }
}
quiz iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos