Sobreescritura de métodos


La herencia permite crear subclases que contienen todos los atributos y métodos privados de la clase superior. Habitualmente en la subclase se definirán, además, atributos y métodos propios que no existían en la superclase. En ocasiones, además interesa que la subclase modifique alguno de los métodos heredados para que tengan un comportamiento distinto. Esto se realiza mediante la sobreescritura de metodos. Simplemente consiste en implementar en la subclase un método que ya existía en la superclase.

 1  
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Esfera {

    double radio;

    void mostrarValores() {
        System.out.println("Radio = " + radio);
    }
}

class Planeta extends Esfera {

    int numSatelites;

    void mostrarValores() {
        System.out.println("Radio = " + radio + "  -  Num. Sat.= " + numSatelites);
    }
}

En este ejemplo la clase Planeta hereda el método mostrarValores() de Esfera, pero luego lo sobreescribe para poder mostrar tanto el radio como el número de satélites. En esta situación el método mostrarValores ejecutará un código distinto  dependiendo del objeto sobre el que se invoque.

 1  
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class EjemploSobreescritura {

    public static void main(String[] args) {
        Esfera e = new Esfera();
        e.radio = 10;
        Planeta p = new Planeta();
        p.radio = 6378;
        p.numSatelites = 1;
        e.mostrarValores();     // Muestra los valores de la esfera
        p.mostrarValores();     // Muestra los valores del planeta
    }
}

El resultado de este programa sería:

Radio = 10
Radio = 6378  -  Num. Sat.= 1 

Supongamos que tenemos las siguientes clases:

 1  
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Nave {

    int posX, posY;
    int municion;

    Nave() {
    }

    void moverDerecha(int dist) {
    }

    void moverIzquierda(int dist) {
    }

    void disparar() {
        if (municion > 0) {
            municion--;
        }
    }

    void dibujar() {
    }
}

class NaveConEscudo extends Nave {

    boolean escudo;

    NaveConEscudo() {
        escudo = false;
    }

    void activarEscudo() {
        escudo = true;
    }

    void desactivarEscudo() {
        escudo = false;
    }
}

En este ejemplo podría ser interesante que NaveConEscudo modificase el comportamiento de alguno de los métodos heredados de Nave. Por ejemplo, que no pueda disparar si tiene el escudo activado. Para ello, tal y como se ha visto, bastaría con sobreescribir el método correspondiente en la subclase:

 1  
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class NaveConEscudo extends Nave {

    boolean escudo;

    NaveConEscudo() {
        escudo = false;
    }

    void activarEscudo() {
        escudo = true;
    }

    void desactivarEscudo() {
        escudo = false;
    }

    // Sobreescribimos el metodo disparar ´
    void disparar() {
        if (escudo == false && municion > 0) {
            municion--;
        }
    }
}

De este modo cada nave tiene su propia versión del método disparar. De forma similar podría sobreescribirse el método dibujar para que cada tipo de nave tuviese una representación gráfica distinta.

La sobreescritura de un método podemos enfocarla desde dos puntos de vista: reescribir el método completamente ignorando el código que hubiese en la superclase, o ampliar el código existente en la superclase con nuevas instrucciones. En el primer caso hablaremos de reemplazo y en el segundo de refinamiento. 

Los ejemplos vistos anteriormente corresponden a sobreescritura mediante reemplazo. Para implementar la sobreescritura mediante refinamiento se debe invocar desde el método sobreescrito de la subclase el método correspondiente de la superclase mediante el uso de super. Por ejemplo podríamos pensar que una NaveConEscudo se dibuja como una Nave con algunos elementos extras. En este caso sería más interesante el refinamiento que el reemplazo, ya que aprovecharíaamos el código del
método dibuja() escrito para la clase Nave.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Nave {

    void dibujar() {
        // Codigo para dibujar una nave b ´ asica ´
    }
}

class NaveConEscudo extends Nave {

    void dibujar() {
        super.dibujar();     // Primero dibujamos una nave basica. ´
        // Codigo para dibujar los elementos extra ´

    }
}

Comentarios