Menu
Coddy logo textTech

Servicio de alquiler de vehículos

Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 87 de 87.

Para este desafío final, construirás un sistema de Servicio de Alquiler de Vehículos que reúne todos los conceptos de POO que has dominado a lo largo de este curso.

Su sistema debe modelar una flota de diferentes tipos de vehículos. Considere una clase base Vehicle con propiedades comunes como la matrícula, la marca y la tarifa de alquiler diaria. Las subclases como Car, Motorcycle y Truck pueden extender esto con atributos específicos como el número de asientos, el tamaño del motor o la capacidad de carga.

Las interfaces pueden definir comportamientos de alquiler: una interfaz Rentable podría declarar métodos como rent(), returnVehicle() y calculateCost(int days). Diferentes tipos de vehículos podrían implementar estrategias de precios de manera diferente, lo que hace que este sea un caso de uso perfecto para el polimorfismo.

Piensa en cómo la clase RentalAgency gestiona la flota utilizando composición.

Las excepciones personalizadas como VehicleNotAvailableException pueden manejar casos extremos.

Podrías aplicar el patrón Factory para crear vehículos o usar enums para las categorías de vehículos y el estado de alquiler.

Este desafío pone a prueba tu capacidad para diseñar un sistema OOP completo y bien estructurado. ¡Buena suerte!

challenge icon

Desafío

Fácil

¡Vamos a construir un Servicio de Alquiler de Vehículos completo que reúna todo lo que has aprendido sobre OOP! Crearás un sistema que gestiona una flota de diferentes tipos de vehículos, maneja alquileres con la validación adecuada y utiliza un patrón de fábrica para crear vehículos.

Organizarás tu código en siete archivos:

  • RentalStatus.java: Crea un enum que represente el estado de alquiler de un vehículo. Incluye los valores AVAILABLE, RENTED y MAINTENANCE. Añade un campo privado description (String), un constructor y un getter. AVAILABLE debe tener la descripción "ready to rent", RENTED debe tener "currently in use" y MAINTENANCE debe tener "under service".
  • VehicleNotAvailableException.java: Crea una excepción personalizada que extienda de Exception. El constructor debe aceptar una matrícula (license plate) y crear un mensaje con el formato Vehicle not available: [licensePlate].
  • Rentable.java: Crea una interfaz que defina las operaciones de alquiler. Declara los métodos rent() que devuelve un boolean, returnVehicle() que devuelve un boolean y calculateCost(int days) que devuelve un double.
  • Vehicle.java: Crea una clase base abstracta para todos los vehículos. Incluye campos privados para licensePlate (String), brand (String), dailyRate (double) y status (RentalStatus, inicializado en AVAILABLE). El constructor recibe licensePlate, brand y dailyRate. Incluye los getters apropiados y un setter para status. Declara un método abstracto getVehicleType() que devuelva un String. Implementa un método getDetails() que devuelva "[licensePlate] [brand] ([vehicleType]) - $[dailyRate]/day - [status description]" con dailyRate formateado a 2 decimales.
  • Car.java: Crea una clase que extienda de Vehicle e implemente Rentable. Añade un campo privado seats (int). El constructor recibe licensePlate, brand, dailyRate y seats. Implementa getVehicleType() para que devuelva "Car". Para rent(), si el estado es AVAILABLE, cámbialo a RENTED y devuelve true; de lo contrario, devuelve false. Para returnVehicle(), si el estado es RENTED, cámbialo a AVAILABLE y devuelve true; de lo contrario, devuelve false. Para calculateCost(int days), devuelve dailyRate multiplicado por days.
  • Motorcycle.java: Crea una clase que extienda de Vehicle e implemente Rentable. Añade un campo privado engineCC (int). El constructor recibe licensePlate, brand, dailyRate y engineCC. Implementa getVehicleType() para que devuelva "Motorcycle". Implementa los métodos de Rentable de la misma manera que en Car, pero calculateCost() debe aplicar un descuento del 10% (multiplicar por 0.9).
  • RentalAgency.java: Crea una clase que gestione la flota de vehículos usando un ArrayList. Incluye los métodos:
    • addVehicle(Vehicle vehicle) - añade un vehículo a la flota
    • findVehicle(String licensePlate) - devuelve el Vehicle o null
    • rentVehicle(String licensePlate, int days) - busca el vehículo, intenta alquilarlo (haciendo casting a Rentable) y devuelve el costo del alquiler. Lanza VehicleNotAvailableException si el vehículo no se encuentra o si rent() devuelve false
    • returnVehicle(String licensePlate) - busca y devuelve el vehículo, retornando true si tiene éxito
    • getAvailableVehicles() - devuelve un ArrayList de vehículos con estado AVAILABLE
  • Main.java: ¡Construye tu servicio de alquiler! Recibirás una cadena de comandos separados por comas:
    • ADD_CAR:licensePlate:brand:dailyRate:seats
    • ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC
    • RENT:licensePlate:days
    • RETURN:licensePlate
    • AVAILABLE

    Procesa cada comando e imprime:

    • ADD_CAR/ADD_MOTORCYCLE: Added: [brand] ([vehicleType])
    • RENT: Rented [licensePlate] for [days] days - Total: $[cost] (costo con 2 decimales), o Error: [exception message]
    • RETURN: Returned: [licensePlate] o Return failed: [licensePlate]
    • AVAILABLE: Imprime Available vehicles: seguido de los detalles de cada vehículo disponible en líneas separadas

    Después de todos los comandos, imprime --- Fleet Summary --- seguido de los detalles de cada vehículo.

Recibirás una entrada: la cadena de comandos separados por comas.

Por ejemplo, con la 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, tu salida sería:

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 desafío combina herencia (jerarquía de Vehicle), interfaces (Rentable), enums (RentalStatus), excepciones personalizadas, polimorfismo (tratar diferentes tipos de vehículos de manera uniforme) y composición (RentalAgency gestionando vehículos) en un sistema de servicio de alquiler completo!

Pruébalo tú mismo

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: Crear una instancia de RentalAgency
        
        // TODO: Dividir la entrada por comas para obtener los comandos individuales
        
        // TODO: Procesar 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 decimales)
        //                           o "Error: [exception message]" si se lanza una excepción
        // RETURN:licensePlate -> imprimir "Returned: [licensePlate]" o "Return failed: [licensePlate]"
        // AVAILABLE -> imprimir "Available vehicles:" seguido de los detalles de cada vehículo disponible
        
        // TODO: Después de todos los comandos, imprimir "--- Fleet Summary ---"
        // seguido de los detalles de cada vehículo
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos