La herencia, es una de las características mas importantes en la programación orientada a objetos debido a que esta permite ahorrar código de manera considerable. Ademas, permite realizar el desarrollo de software de una manera mas organizada.

Herencia, esta palabra dice de lo que trata y es que extends es una palabra reservada en java y me permite heredar de otras clases. Sin embargo, no se puede heredar de cualquier clase ya que debe aplicarse una regla (realmente solo es una frase). Antes de heredar usted debe preguntarse lo siguiente «es un» y «tiene un«.

Ejemplo: Supongamos que se tiene la clase coche, aqui entran en juego las dos frase mencionadas anteriormente.

¿El coche es un?

Asi es, espero hayas pensado lo mismo que yo. El coche es un vehículo y es aqui donde te das cuenta de la utilidad de estas frases. Ahora que ya sabemos que el coche es un vehículo podemos aplicar la siguiente frase.

¿El vehículo tiene un?

El vehículo, tiene un volante, asientos, llantas, velocidades. Realmente esta pregunta te permite saber que atributos debes agregar a tu clase.

En este caso la clase vehículo es nuestra superclase y la clase coche que hereda de vehículo es nuestra subclase. Ahora pondre un ejemplo para aclarar el tema:

Primero creamos una clase nombrada Padre:

package herencia;

public class Padre {

    public Padre(String apellido) {
        this.apellido = apellido;
        setCasa("Casa");
    }
    
    public String getApellido() {
        return apellido;
    }

    public void setCasa(String casa) {
        this.casa = casa;
    }

    public String getCasa() {
        return casa;
    }
    
    public String mensaje() {
        return "Apellido: " + apellido;
    }

    private String casa;
    private String apellido;

}

El padre es nuestra superclase y este tiene como atributo (propiedad) una casa la cual va a heredar su hijo (en este caso la clase hereda de padre). A continuación se crea la clase hijoDePadre este hijo hereda la casa de su padre, ademas ahora el hijo puede tener sus propios atributos (propiedades o cosas materiales, como lo quieras ver).

El hijo se ha comprado un coche, por ende esta propiedad se agrega a la clase.

package herencia;

public class hijoDePadre extends Padre {

    public hijoDePadre(String apellido, int edad) {
        super(apellido);
        this.edad = edad;
        setCoche("Coche");
    }

    public void setCoche(String coche) {
        this.coche = coche;
    }

    public String getCoche() {
        return coche;
    }
    
    @Override
    public String mensaje() {
        return super.mensaje() + " Edad: " + edad;
    }

    private String coche;
    private int edad;

}

Sin embargo, como la clase padre recibe por parametro un apellido (se puede decir que el hijo esta heredando el apellido) por lo cual debemos especificar en nuestra clase hijoDePadre un constructor que pase por parametro el apellido (el cual heredo del padre) mas otros valores que deseemos agregar (en este caso la edad).

La palabra reservada super me permite llamar al constructor o metodos de clase que estoy heredando, en este caso nosotros vamos a llamar el metodo mensaje y al constructor de la clase Padre.

Podemos observar que cuando ponemos un punto delante de super (ejemplo: super.mensaje()) le indicamos que estamos llamando al metodo de la clase que estamos heredando y si solamente ponemos la palabra super acompañada de parentesis indicamos la llamada al constructor de la clase Padre (ejemplo: super(apellido)).

Por un lado la llamada al constructor padre me permite iniciar los valores de las variables (en este caso la variable apellido, permitiendo llamar al metodo mensaje de la clase padre (esto hace que nuestra variable apellido no devuelva un valor nulo). Sino llamas al constructor padre el propio compilador te indicara un error).

Ahora creamos la clase HijoDeHijoDePadre, podría sonar raro. Pero traduciendo un poco al español, la clase padre se convierte en abuelo, la clase hijoDePadre se convierte en padre, espero no confundirte (pero podrías pensarlo como en la vida real y entenderas).

package herencia;

public class hijoDeHijoDePadre extends hijoDePadre {

    public hijoDeHijoDePadre(String nombre, int edad) {
        super(nombre, edad);
        setXbox("Xbox");
    }

    public void setXbox(String xbox) {
        this.xbox = xbox;
    }

    public String getXbox() {
        return xbox;
    }

    private String xbox;

}

Esto podrás entenderlo con las explicaciones que he realizado hasta el momento, finalmente solo creamos la clase para usar los metodos creados:

package herencia;

public class HerenciaMain {
    
    public static void main(String[] args) {

        hijoDeHijoDePadre heredo = new hijoDeHijoDePadre("Ramirez", 20);

        System.out.println("El hijo de apellido " + heredo.getApellido() + 
                "heredo del abuelo una: " + heredo.getCasa() + ", del padre un: "
                + heredo.getCoche() + " y la unica pertenencia propia es: " + heredo.getXbox());
        System.out.println("Mensaje=> " + heredo.mensaje());

    }
    
}

Me olvidaba de decir que la palabra reservada extends hace posible la herencia, ya que permite extender los atributos de una clase.