Semana 7: Herencia en Programación Orientada a Objetos (Java)
¿Qué es la Herencia?
La herencia es uno de los pilares fundamentales de la Programación Orientada a Objetos (POO). Permite que una clase (llamada clase hija o subclase) herede atributos y métodos de otra clase (llamada clase padre o superclase).
Características principales:
- Reutilización de código: Evita duplicar código común
- Jerarquía de clases: Establece relaciones "es-un" entre objetos
- Extensibilidad: Permite agregar funcionalidad específica a las subclases
- Polimorfismo: Facilita el tratamiento uniforme de objetos relacionados
Sintaxis en Java
En Java, utilizamos la palabra clave extends para establecer herencia:
class ClasePadre {
// Atributos y métodos de la clase padre
}
class ClaseHija extends ClasePadre {
// Atributos y métodos adicionales de la clase hija
// Hereda automáticamente todo lo público y protegido del padre
}
Ejemplo Básico: Vehículos
Clase Padre (Superclase)
public class Vehiculo {
protected String marca;
protected String modelo;
protected int año;
protected double velocidad;
// Constructor
public Vehiculo(String marca, String modelo, int año) {
this.marca = marca;
this.modelo = modelo;
this.año = año;
this.velocidad = 0.0;
}
// Métodos comunes a todos los vehículos
public void acelerar(double incremento) {
velocidad += incremento;
System.out.println("Acelerando... Velocidad actual: " + velocidad + " km/h");
}
public void frenar(double decremento) {
velocidad = Math.max(0, velocidad - decremento);
System.out.println("Frenando... Velocidad actual: " + velocidad + " km/h");
}
public void mostrarInfo() {
System.out.println("Vehículo: " + marca + " " + modelo + " (" + año + ")");
}
// Getters
public String getMarca() { return marca; }
public String getModelo() { return modelo; }
public int getAño() { return año; }
public double getVelocidad() { return velocidad; }
}
Clases Hijas (Subclases)
Clase Auto
public class Auto extends Vehiculo {
private int numeroPuertas;
private String tipoCombustible;
// Constructor que llama al constructor del padre
public Auto(String marca, String modelo, int año, int numeroPuertas, String tipoCombustible) {
super(marca, modelo, año); // Llamada al constructor del padre
this.numeroPuertas = numeroPuertas;
this.tipoCombustible = tipoCombustible;
}
// Método específico de Auto
public void encenderAireAcondicionado() {
System.out.println("Aire acondicionado encendido en el " + marca + " " + modelo);
}
// Sobrescritura (Override) del método mostrarInfo
@Override
public void mostrarInfo() {
super.mostrarInfo(); // Llama al método del padre
System.out.println("Tipo: Auto");
System.out.println("Puertas: " + numeroPuertas);
System.out.println("Combustible: " + tipoCombustible);
}
// Getters específicos
public int getNumeroPuertas() { return numeroPuertas; }
public String getTipoCombustible() { return tipoCombustible; }
}
Clase Motocicleta
public class Motocicleta extends Vehiculo {
private int cilindrada;
private boolean tieneSidecar;
public Motocicleta(String marca, String modelo, int año, int cilindrada, boolean tieneSidecar) {
super(marca, modelo, año);
this.cilindrada = cilindrada;
this.tieneSidecar = tieneSidecar;
}
// Método específico de Motocicleta
public void hacerCaballito() {
if (velocidad > 20) {
System.out.println("¡Haciendo caballito con la " + marca + " " + modelo + "!");
} else {
System.out.println("Necesitas más velocidad para hacer caballito.");
}
}
@Override
public void mostrarInfo() {
super.mostrarInfo();
System.out.println("Tipo: Motocicleta");
System.out.println("Cilindrada: " + cilindrada + "cc");
System.out.println("Sidecar: " + (tieneSidecar ? "Sí" : "No"));
}
public int getCilindrada() { return cilindrada; }
public boolean isTieneSidecar() { return tieneSidecar; }
}
Conceptos Importantes
1. La palabra clave super
super(): Llama al constructor de la clase padresuper.metodo(): Llama a un método de la clase padresuper.atributo: Accede a un atributo de la clase padre
2. Sobrescritura de métodos (@Override)
Permite que una subclase proporcione una implementación específica de un método que ya está definido en su superclase.
@Override
public void mostrarInfo() {
super.mostrarInfo(); // Opcional: llamar al método del padre
// Agregar funcionalidad específica
System.out.println("Información adicional específica");
}
3. Modificadores de acceso en herencia
public: Accesible desde cualquier lugarprotected: Accesible desde la misma clase, subclases y mismo paqueteprivate: NO heredable, solo accesible desde la misma clase- Sin modificador (package-private): Accesible desde el mismo paquete
Ejemplo de Uso Completo
public class EjemploHerencia {
public static void main(String[] args) {
// Crear objetos de diferentes tipos
Auto miAuto = new Auto("Toyota", "Corolla", 2023, 4, "Gasolina");
Motocicleta miMoto = new Motocicleta("Yamaha", "R1", 2022, 1000, false);
System.out.println("=== INFORMACIÓN DE VEHÍCULOS ===");
miAuto.mostrarInfo();
System.out.println();
miMoto.mostrarInfo();
System.out.println("\n=== PROBANDO FUNCIONALIDADES ===");
// Métodos heredados (disponibles en ambos)
miAuto.acelerar(50);
miMoto.acelerar(80);
// Métodos específicos de cada clase
miAuto.encenderAireAcondicionado();
miMoto.hacerCaballito();
// Polimorfismo: tratar objetos diferentes de manera uniforme
System.out.println("\n=== POLIMORFISMO ===");
Vehiculo[] vehiculos = {miAuto, miMoto};
for (Vehiculo vehiculo : vehiculos) {
vehiculo.mostrarInfo(); // Llama al método sobrescrito correspondiente
vehiculo.acelerar(20);
System.out.println();
}
}
}
Ventajas de la Herencia
- Reutilización de código: Evita duplicación
- Mantenimiento: Cambios en la clase padre se propagan automáticamente
- Organización: Crea jerarquías lógicas y comprensibles
- Extensibilidad: Fácil agregar nuevas funcionalidades
- Polimorfismo: Permite tratar objetos relacionados de manera uniforme
Consideraciones Importantes
- Java solo permite herencia simple (una clase solo puede extender una clase)
- Todas las clases en Java heredan implícitamente de
Object - Los constructores NO se heredan, pero se pueden llamar con
super() - Los métodos
privateNO se heredan - Los métodos
staticse heredan pero no se pueden sobrescribir
Buena Práctica
Usa herencia cuando existe una relación "es-un" clara. Por ejemplo: "Un Auto ES-UN Vehículo", "Una Motocicleta ES-UN Vehículo".
Cuidado
No abuses de la herencia. A veces la composición ("tiene-un") es más apropiada que la herencia ("es-un").
Actividades Prácticas
Ejercicio 1: Sistema de Animales
Crea una jerarquía de clases para un zoológico:
- Clase padre Animal con atributos: nombre, edad, peso
- Clases hijas: Mamifero, Ave, Reptil
- Cada clase hija debe tener atributos y métodos específicos
- Implementa sobrescritura del método hacerSonido()
Ejercicio 2: Sistema de Figuras Geométricas
Implementa una jerarquía para figuras geométricas:
- Clase padre Figura con atributos: color, nombre
- Clases hijas: Circulo, Rectangulo, Triangulo
- Métodos para calcular área y perímetro en cada clase hija
- Método mostrarInformacion() sobrescrito en cada clase
Ejercicio 3: Sistema de Productos
Crea un sistema de productos para una tienda:
- Clase padre Producto con: código, nombre, precio
- Clases hijas: ProductoElectronico, ProductoAlimenticio
- Implementa métodos específicos como calcularGarantia() y verificarVencimiento()
Consejos para los Ejercicios
- Usa
protectedpara atributos que las clases hijas necesiten acceder - Implementa constructores que llamen a
super() - Sobrescribe métodos cuando necesites comportamiento específico
- Usa
@Overridepara mayor claridad en el código