Ejercicio 8: Gestión de Empleados y Polimorfismo
Enunciado
El objetivo de este ejercicio es desarrollar un pequeño sistema de gestión de empleados utilizando los pilares de la Programación Orientada a Objetos. Todos los empleados comparten comportamientos comunes, pero cada tipo calcula su salario de forma distinta.
Requisitos
- Clase base Empleado: Debe contener el atributo
nombrey el métodopublic double calcularSalario()(que devuelve 0 en la base). - Clases hijas:
EmpleadoFijo: AtributosalarioMensual. Sobrescribe el cálculo devolviendo dicho salario.EmpleadoPorHoras: AtributoshorasTrabajadasyprecioHora. Sobrescribe el cálculo devolviendo el producto de ambos.
- Programa principal: En la clase
Main, crear una colección de empleados, añadir instancias de cada tipo y mostrar su información recorriendo la lista.
Restricciones
No se permite el uso de---instanceof, ni estructurasifoswitchpara distinguir los tipos de empleados. El comportamiento debe resolverse exclusivamente mediante polimorfismo desde una referencia de tipoEmpleado.
Solución Propuesta
A continuación se presenta la implementación completa incluyendo la ampliación opcional: el tipo EmpleadoComision, el uso de toString() y la aplicación de una subida salarial común.
1. Jerarquía de Clases
Definimos la clase base y sus especializaciones. Es fundamental que aumentarSalario esté presente en la clase base para poder invocarlo de forma polimórfica.
package Tema5.Ejercicios.ejercicio8;
// Clase base Empleado
class Empleado {
private String nombre;
public Empleado(String nombre) {
this.nombre = nombre;
}
public String getNombre() {
return nombre;
}
public double calcularSalario() {
return 0.0;
}
// Método para subir salario común (establece el contrato)
public void aumentarSalario(double porcentaje) {
// Implementación genérica o vacía según el diseño
}
// Uso de toString para formatear la salida
@Override
public String toString() {
return String.format("Nombre: %s - Salario: %.2f", nombre, calcularSalario());
}
}
// Empleado con salario mensual fijo
class EmpleadoFijo extends Empleado {
private double salarioMensual;
public EmpleadoFijo(String nombre, double salarioMensual) {
super(nombre);
this.salarioMensual = salarioMensual;
}
@Override
public double calcularSalario() {
return salarioMensual;
}
@Override
public void aumentarSalario(double porcentaje) {
this.salarioMensual += this.salarioMensual * (porcentaje / 100);
}
}
// Empleado por horas
class EmpleadoPorHoras extends Empleado {
private int horasTrabajadas;
private double precioHora;
public EmpleadoPorHoras(String nombre, int horasTrabajadas, double precioHora) {
super(nombre);
this.horasTrabajadas = horasTrabajadas;
this.precioHora = precioHora;
}
@Override
public double calcularSalario() {
return horasTrabajadas * precioHora;
}
@Override
public void aumentarSalario(double porcentaje) {
this.precioHora += this.precioHora * (porcentaje / 100);
}
}
// Empleado a comisión (Ampliación)
class EmpleadoComision extends Empleado {
private double ventasTotales;
private double porcentajeComision;
public EmpleadoComision(String nombre, double ventasTotales, double porcentajeComision) {
super(nombre);
this.ventasTotales = ventasTotales;
this.porcentajeComision = porcentajeComision;
}
@Override
public double calcularSalario() {
return ventasTotales * porcentajeComision;
}
@Override
public void aumentarSalario(double porcentaje) {
this.porcentajeComision += this.porcentajeComision * (porcentaje / 100);
}
}
2. Clase Main
En el programa principal, tratamos a todos los objetos de forma genérica a través de la clase Empleado.
package Tema5.Ejercicios.ejercicio8;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// Crear colección de empleados
ArrayList<Empleado> listaEmpleados = new ArrayList<>();
// Añadir diferentes tipos de empleados
listaEmpleados.add(new EmpleadoFijo("Ana García", 2000.0));
listaEmpleados.add(new EmpleadoPorHoras("Luis Pérez", 40, 15.5));
listaEmpleados.add(new EmpleadoComision("Sofia Martinez", 50000.0, 0.05));
System.out.println("--- Listado de nóminas inicial ---");
imprimirNominas(listaEmpleados);
System.out.println("\nAplicando una subida salarial del 10%...");
for (Empleado e : listaEmpleados) {
e.aumentarSalario(10);
}
imprimirNominas(listaEmpleados);
}
// Método polimórfico para recorrer y mostrar información
public static void imprimirNominas(ArrayList<Empleado> empleados) {
for (Empleado emp : empleados) {
System.out.println(emp.toString());
}
}
}
Pregunta de Reflexión
¿Por qué este diseño sigue funcionando aunque se añadan nuevos tipos de empleados sin modificar el main?
Este diseño sigue funcionando gracias al Polimorfismo y al cumplimiento del Principio de Abierto/Cerrado. El método main está programado para trabajar con la abstracción Empleado. Java utiliza la ligadura dinámica (late binding) para determinar en tiempo de ejecución qué implementación específica de calcularSalario o aumentarSalario debe llamar según el objeto real almacenado en la referencia. Esto permite extender el sistema con nuevas clases sin alterar la lógica de control ya existente.