Herencia en Java: Reutiliza y Extiende tu Código como un Pro

Herencia en Java: Reutiliza y Extiende tu Código como un Pro

¿Te ha pasado que al programar te encuentras escribiendo el mismo código en diferentes clases?
A mí sí, y créeme: es el primer síntoma de que necesitas herencia.
Hoy te explico cómo Java te permite heredar características y comportamientos entre clases, para que escribas menos y tu código sea más limpio y mantenible.


¿Qué es la herencia?

Imagina una familia. Todos los miembros tienen ciertas características en común (color de ojos, apellido…), pero cada uno también tiene sus propias cualidades. En Java, una clase puede heredar atributos y métodos de otra, tal como un hijo hereda cosas de sus padres.

// Clase base (superclase)
public class Animal {
    String nombre;
    void comer() {
        System.out.println(nombre + " está comiendo.");
    }
}

// Subclase (hereda de Animal)
public class Perro extends Animal {
    void ladrar() {
        System.out.println(nombre + " está ladrando. ¡Guau!");
    }
}
💡 Info: extends es la palabra clave mágica que hace posible la herencia en Java. Así, Perro hereda los atributos y métodos de Animal.

Jerarquías de herencia: construye tu árbol genealógico de clases

Puedes crear jerarquías tan profundas como necesites, siempre pensando en que todo mantenga sentido lógico.

// Jerarquía de clases
public class Animal { /* ... */ }
public class Mamifero extends Animal { /* ... */ }
public class Perro extends Mamifero { /* ... */ }
  • Animal es la raíz (base).
  • Mamífero hereda de Animal y puede agregar características propias.
  • Perro hereda de Mamífero y tiene sus métodos particulares.

Así puedes construir jerarquías para cualquier dominio: vehículos, empleados, dispositivos, etc.


El uso de super: accediendo a lo de “arriba”

A veces, la subclase necesita invocar métodos o constructores de la superclase. Para eso está la palabra clave super.

Ejemplo: usando el constructor de la superclase

public class Animal {
    String nombre;
    public Animal(String nombre) {
        this.nombre = nombre;
    }
}

public class Gato extends Animal {
    public Gato(String nombre) {
        super(nombre); // Llama al constructor de Animal
    }
}
💡 Info: super se usa para acceder a métodos o atributos de la superclase, y es obligatorio al construir si la superclase no tiene constructor vacío.

¿Existe la herencia múltiple en Java?

Aquí viene la pregunta de oro: ¿Puedo heredar de más de una clase?

🚫 Importante: Java NO permite herencia múltiple directa entre clases. Es decir, una clase solo puede extender de una superclase.

¿Por qué?

Principalmente para evitar ambigüedades, como el famoso “Diamond Problem”, donde una subclase no sabría qué implementación heredar si dos superclases tienen el mismo método.


Simulando herencia múltiple con interfaces

Aunque no puedes extender dos clases, sí puedes implementar varias interfaces. Las interfaces te permiten definir comportamientos que tu clase debe cumplir, sin importar su lugar en la jerarquía.

public interface Nadador {
    void nadar();
}

public interface Corredor {
    void correr();
}

public class Triatleta extends Animal implements Nadador, Corredor {
    public Triatleta(String nombre) {
        super(nombre);
    }

    @Override
    public void nadar() {
        System.out.println(nombre + " está nadando.");
    }

    @Override
    public void correr() {
        System.out.println(nombre + " está corriendo.");
    }
}
  • Aquí, Triatleta hereda de Animal y puede nadar y correr gracias a las interfaces.
⚠️ Consejo: Usa interfaces para compartir comportamientos entre clases no relacionadas, y herencia de clases solo cuando exista una clara relación “es-un”.

Ejemplo de la vida real: Vehículos

Supón que tienes diferentes tipos de vehículos. Todos heredan de una clase Vehiculo, pero algunos además pueden volar o navegar, gracias a interfaces.

public class Vehiculo {
    String marca;
    void encender() {
        System.out.println("El vehículo se ha encendido.");
    }
}

public interface Volador {
    void volar();
}

public interface Navegable {
    void navegar();
}

public class Avion extends Vehiculo implements Volador {
    @Override
    public void volar() {
        System.out.println("El avión está volando.");
    }
}

public class Barco extends Vehiculo implements Navegable {
    @Override
    public void navegar() {
        System.out.println("El barco está navegando.");
    }
}

public class Hidroavion extends Vehiculo implements Volador, Navegable {
    @Override
    public void volar() {
        System.out.println("El hidroavión está volando.");
    }
    @Override
    public void navegar() {
        System.out.println("El hidroavión está navegando.");
    }
}

Resumen

  • Herencia = reutiliza código, crea jerarquías lógicas y evita repeticiones.
  • super = accede a constructores/métodos de la clase padre.
  • Herencia múltiple directa NO existe, pero las interfaces te dan flexibilidad y poder para compartir comportamientos.
  • Siempre piensa: “¿mi clase es realmente un tipo de X?” antes de usar herencia.
💡 Sugerencia: Cuando dudes, comienza por composición e interfaces. La herencia es poderosa, pero úsala con moderación y sentido.