Ampliación de la jerarquía de clases

prev.gif (997 bytes)chapter.gif (1105 bytes)home.gif (1054 bytes)next.gif (998 bytes)

La herencia y el polimorfismo

Añadiendo nuevas clases a la jerarquía

El polimorfismo en acción

El operador instanceof

Resumen


Añadiendo nuevas clases a la jerarquía

disco.gif (1035 bytes)figura1: Figura.java, FiguraApp1.java

Ampliamos el árbol jerárquico de las clases que describen las figuras planas regulares, para acomodar a dos clases que describen las figuras planas, triángulo y cuadrado. La relación jerárquica se muestra en la figura.

herencia2.gif (1651 bytes)

La clase Cuadrado es una clase especializada de Rectangulo, ya que un cuadrado tiene los lados iguales. El constructor solamente precisa de tres argumentos los que corresponden a la posición de la figura y a la longitud del lado

class Cuadrado extends Rectangulo{
    public Cuadrado(int x, int y, double dimension){
        super(x, y, dimension, dimension);
    }
}

El constructor de la clase derivada llama al constructor de la clase base y le pasa la posición x e y de la figura, el ancho y alto que tienen el mismo valor. No es necesario redefinir una nueva función area. La clase Cuadrado hereda la función area definida en la clase Rectangulo.

La clase derivada Triángulo, tiene como datos, aparte de su posición (x, y) en el plano, la base y la altura del triángulo.

class Triangulo extends Figura{
    protected double base, altura;
    public Triangulo(int x, int y, double base, double altura){
        super(x, y);
        this.base=base;
        this.altura=altura;
    }
    public double area(){
        return base*altura/2;
    }
}

El constructor de la clase Triangulo llama al constructor de la clase Figura, le pasa las coordenadas x e y de su centro, y luego inicializa los miembros dato base y altura.

En la definición de la función area, se calcula el área del triángulo como producto de la base por la altura y dividido por dos.

 

El polimorfismo en acción

Veamos ahora la llamada a la función figuraMayor. Primero, creamos un array del tipo Figura, guardando en sus elementos las direcciones devueltas por new al crear cada uno de los objetos.

        Figura[] fig=new Figura[4];
        fig[0]=new Rectangulo(0,0, 5.0, 2.0);
        fig[1]=new Circulo(0,0, 3.0);
        fig[2]=new Cuadrado(0, 0, 5.0);
        fig[3]=new Triangulo(0,0, 7.0, 12.0);

	Figura fMayor=figuraMayor(fig);
        System.out.println("El área mayor es "+fMayor.area());

Pasamos el array fig a la función figuraMayor, el valor que retorna lo guardamos en fMayor. Para conocer el valor del área, desde fMayor se llamará a la función miembro area. Se llamará a la versión correcta dependiendo de la referencia al tipo de objeto que guarda fMayor.

Si fMayor guarda una referencia a un objeto de la clase Circulo, llamará a la función area definida en dicha clase. Si fMayor guarda una referencia a un objeto de la clase Triangulo, llamará a la función area definida en dicha clase, y así sucesivamente.

 

El operador instanceof

El operador instanceof tiene dos operandos: un objeto en el lado izquierdo y una clase en el lado derecho. Esta expresión devuelve true o false dependiendo de que el objeto situado a la izquierda sea o no una instancia de la clase situada a la derecha o de alguna de sus clases derivadas.

Por ejemplo.

	Rectangulo rect=new Rectangulo(0, 0, 5.0, 2.0);
	rect instanceof String  	//false
	rect instanceof Rectangulo  	//true

El objeto rect de la clase Rectangulo no es un objeto de la clase String. El objeto rect si es un objeto de la clase Rectangulo.

Veamos la relación entre rect y las clases de la jerarquía

	rect instanceof Figura  	//true
	rect instanceof Cuadrado  	//false

rect es un objeto de la clase base Figura pero no es un objeto de la clase derivada Cuadrado

 

Resumen

La herencia es la propiedad que permite la creación de nuevas clases a partir de clases ya existentes. La clase derivada hereda los datos y las funciones miembro de la clase base, y puede redefinir algunas de las funciones miembro o definir otras nuevas, para ampliar la funcionalidad que ha recibido de la clase base.

Para crear un objeto de la clase derivada se llama primero al constructor de la clase base mediante la palabra reservada super. Luego, se inicializa los miembros dato de dicha clase derivada

El polimorfismo se implementa por medio de las funciones abstractas, en las clases derivadas se declara y se define una función que tiene el mismo nombre, el mismo número de parámetros y del mismo tipo que en la clase base, pero que da lugar a un comportamiento distinto, específico de los objetos de la clase derivada.

Enlace dinámico significa que la decisión sobre la función a llamar se demora hasta el tiempo de ejecución del programa.

No se pueden crear objetos de una clase abstracta pero si se pueden declarar referencias en las que guardamos el valor devuelto por new al crear objetos de las clases derivadas. Esta peculiaridad nos permite pasar un objeto de una clase derivada a una función que conoce el objeto solamente por su clase base. De este modo podemos ampliar la jerarquía de clases sin modificar el código de las funciones que manipulan los objetos de las clases de la jerarquía.