Skip to content

2 Constructores

Super

A veces se requiere llamar a un método de la superclase. Eso se realiza con la palabra reservada super. En el tema 4. Programación Orientada a Objetos vimos que this es una variable que hace referencia al objeto actual, pues super es una variable que hace referencia a la superclase del objeto actual, por lo tanto es un método imprescindible para poder acceder a métodos anulados por herencia.

public class Car extends Vehicle {
    private double gasoline;

    public double getGasoline() {
        return gasoline;
    }

    public void refuel(double liters) {
        gasoline += liters;
    }

    @Override
    public void accelerate(double amount){
        super.accelerate(amount); // Llamo al accelerate del padre
        gasoline *= 0.9;
    }
}
public class Super {
    public void show(){
        Car car = new Car();

        car.refuel(40.35);

        System.out.printf("El coche tiene %.2f litros de gasolina, y va a %.2f km/h\n",
                car.getGasoline(), car.getSpeed());

        car.accelerate(100);

        System.out.printf("El coche tiene %.2f litros de gasolina, y va a %.2f km/h\n",
                car.getGasoline(), car.getSpeed());
    }

    public static void main(String[] args) {
        new Super().show();
    }
}
El coche tiene 40,35 litros de gasolina y va a 0,00 km/h
El coche tiene 36,32 litros de gasolina y va a 100,00 km/h

En el ejemplo anterior, super.accelerate(amount) llama al método accelerate de la clase Vehicle el cual acelerará la marcha. Es necesario redefinir el método accelerate en la clase Car ya que aunque la velocidad varía igual que en la superclase, hay que tener en cuenta el consumo de gasolina.

Constructores

Los constructores no se heredan de la superclase a las subclases pero sí se pueden invocar los constructores de la superclase desde los constructores de las subclases mediante super:

public class Vehicle{
    // ...
    public Vehicle(int wheelCount, String color) {
        this.wheelCount = wheelCount;
        this.color = color;
        speed = 0;
    }
    // ...
}
public class Car extends Vehicle{
    //...
    public Car(int wheelCount, String color){
        super(wheelCount, color); // Llama constructor del padre
        gasoline = 0;
    }
    // ...
}
public class Constructors {
    public void show(){
        Vehicle vehicle = new Vehicle(2, "azul");
        Car car = new Car(4, "rojo");

        System.out.printf("Vehículo: %d ruedas y de color %s\n", vehicle.getWheelCount(), vehicle.getColor());
        System.out.printf("Coche: %d ruedas y de color %s\n", car.getWheelCount(), car.getColor());
    }

    public static void main(String[] args) {
        new Constructors().show();
    }
}
Vehículo: 2 ruedas y de color azul
Coche: 4 ruedas y de color rojo

Si una clase no tiene constructor, Java crea uno por defecto. Pero en el caso de que sea una subclase, Java lo crea con la línea de código super(), es decir, con una llamada al constructor de la superclase.

Pero si la superclase tuviera un constructor con parámetros, Java ya no crearía el constructor por defecto Vehicle() y a las subclases les daría un error de compilación con la llamada del super():

public class Vehicle{
    // ...
    /*
     * Tiene un constructor con parámetros, por lo tanto, Java
     * no crea el constructor por defecto
     * Vehicle()
    */
    public Vehicle(int wheelCount, String color) {
        this.wheelCount = wheelCount;
        this.color = color;
        speed = 0;
    }
    // ...
}
public class Car extends Vehicle{
    //...
    /* 
     * No tiene constructor. Java lo crea por defecto con la línea de código 
     * super(), es decir, con una llamada al constructor por defecto de la
     * superclase. Por lo tanto, está llamando a Vehicle(), dando un error 
     * de compilación ya que no se ha creado. 
     */
    // ...
}

Incluso aunque se defina un constructor con parámetros en la clase Car, Java sigue añadiendo de manera implícita la llamada super() en el constructor y como no hay constructor por defecto en la clase Vehicle, continúa dando error de compilación

public class extends Vehicle{
    //...

    /*
     * Java sigue añadiendo de manera implícita la llamada super()
     * en el constructor y como no hay constructor por defecto en
     * la clase Vehicle, da un error de compilación
     */
    public Car(int wheelCount, String color){
        this.wheelCount = wheelCount;
        this.color = color;
        speed = 0;
        gasoline = 0;
    }
    // ...
}

Se puede arreglar realizando una llamada explícita al constructor con parámetros de la superclase:

public class Car extends Vehicle{
    //...
    public Car(int wheelCount, String color){
        super(wheelCount, color); // Llama constructor del padre
        gasoline = 0;
    }
    // ...
}

Si una subclase tiene más constructores, este problema habría que arreglarlo en cada uno de ellos:

public class Car extends Vehicle{
    //...
    public Car(int wheelCount, String color){
        super(wheelCount, color); // Llama constructor del padre
        gasoline = 0;
    }

    public Car(int wheelCount){ // ERROR
        this.wheelCount = count;
        this.color = "blanco";
        speed = 0;
        gasoline = 0;
    }
    // ...
}

Se puede solucionar de dos maneras:

  1. Haciendo una llamada a un constructor de la superclase mediante super.
  2. Haciendo una llamada a un constructor de la propia clase mediante this.

En ambos casos, tienen que ser la primera instrucción del constructor, por lo que el uso de super y this no puede ser simultáneo, lo que significa que hay que elegir entre ambas.

public class Car extends Vehicle{
    //...
    public Car(int wheelCount, String color){
        super(wheelCount, color); // Llama constructor del padre
        gasoline = 0;
    }

    public Car(int wheelCount){ 
        super(wheelCount, "blanco")
        speed = 0;
        gasoline = 0;
    }
    //...
}
public class Car extends Vehicle{
    //...
    public Car(int wheelCount, String color){
        super(wheelCount, color); // Llama constructor del padre
        gasoline = 0;
    }

    public Car(int wheelCount){ 
        this(wheelCount, "blanco")
    }
    //...
}