Introducción
La herencia es una
propiedad esencial de la Programación Orientada a Objetos que consiste en la
creación de nuevas clases a partir de otras ya existentes. Este término ha sido
prestado de la Biología donde afirmamos que un niño tiene la cara de su padre,
que ha heredado ciertas facetas físicas o del comportamiento de sus
progenitores.
La herencia es la
característica fundamental que distingue un lenguaje orientado a objetos, como
el C++ o Java, de otro convencional como C, BASIC, etc. Java permite heredar a
las clases características y conductas de una o varias clases denominadas base.
Las clases que heredan de clases base se denominan derivadas, estas a su vez
pueden ser clases bases para otras clases derivadas. Se establece así una
clasificación jerárquica, similar a la existente en Biología con los animales y
las plantas.
La herencia ofrece
una ventaja importante, permite la reutilización del código. Una vez que una
clase ha sido depurada y probada, el código fuente de dicha clase no necesita
modificarse. Su funcionalidad se puede cambiar derivando una nueva clase que
herede la funcionalidad de la clase base y le añada otros comportamientos.
Reutilizando el código existente, el programador ahorra tiempo y dinero, ya que
solamente tiene que verificar la nueva conducta que proporciona la clase
derivada.
La programación en
los entornos gráficos, en particular Windows, con el lenguaje C++, es un
ejemplo ilustrativo. Los compiladores como los de Borland y Microsoft
proporcionan librerías cuyas clases describen el aspecto y la conducta de las
ventanas, controles, menús, etc. Una de estas clases denominada TWindow describe el aspecto y la conducta de
una ventana, tiene una función miembro denominada Paint, que no dibuja nada en el
área de trabajo de la misma. Definiendo una clase derivada deTWindow,
podemos redefinir en ella la función Paint para que dibuje una figura.
Aprovechamos de este modo la ingente cantidad y complejidad del código
necesario para crear una ventana en un entorno gráfico. Solamente, tendremos
que añadir en la clase derivada el código necesario para dibujar un rectángulo,
una elipse, etc.
En el lenguaje
Java, todas las clases derivan implícitamente de la clase base Object, por lo que heredan las
funciones miembro definidas en dicha clase. Las clases derivadas pueden
redefinir algunas de estas funciones miembro como toString y definir otras nuevas.
Los programadores
crean clases base:
1.
Cuando se dan cuenta que diversos tipos tienen algo en común,
por ejemplo en el juego del ajedrez peones, alfiles, rey, reina, caballos y
torres, son piezas del juego. Creamos, por tanto, una clase base y derivamos
cada pieza individual a partir de dicha clase base.
2.
Cuando se precisa ampliar la funcionalidad de un programa sin
tener que modificar el código existente.
Vamos a poner un ejemplo del segundo tipo, que simule la
utilización de librerías de clases para crear un interfaz gráfico de usuario
como Windows 3.1 o Windows 95.
Supongamos
que tenemos una clase que describe la conducta de una ventana muy simple,
aquella que no dispone de título en la parte superior, por tanto no puede
desplazarse, pero si cambiar de tamaño actuando con el ratón en los bordes
derecho e inferior.
La clase Ventana tendrá los siguientes miembros dato:
la posición x e y de la ventana, de su esquina superior
izquierda y las dimensiones de la ventana:ancho y alto.
public class Ventana {
protected int x;
protected int y;
protected int ancho;
protected int alto;
public Ventana(int x, int y, int ancho, int alto) {
this.x=x;
this.y=y;
this.ancho=ancho;
this.alto=alto;
}
}
Las
funciones miembros, además del constructor serán las siguientes: la función mostrar que simula una ventana en un entorno
gráfico, aquí solamente nos muestra la posición y las dimensiones de la
ventana.
public void mostrar(){
System.out.println("posición : x="+x+", y="+y);
System.out.println("dimensiones : w="+ancho+", h="+alto);
}
La función cambiarDimensiones que simula
el cambio en la anchura y altura de la ventana.
public void cambiarDimensiones(int dw, int dh){
ancho+=dw;
alto+=dh;
}
El código
completo de la clase base Ventana,
es el siguiente
package ventana;
public class Ventana {
protected int x;
protected int y;
protected int ancho;
protected int alto;
public Ventana(int x, int y, int ancho, int alto) {
this.x=x;
this.y=y;
this.ancho=ancho;
this.alto=alto;
}
public void mostrar(){
System.out.println("posición : x="+x+", y="+y);
System.out.println("dimensiones : w="+ancho+", h="+alto);
}
public void cambiarDimensiones(int dw, int dh){
ancho+=dw;
alto+=dh;
}
}
|
Objetos de la clase base
Como vemos
en el código, el constructor de la clase base inicializa los cuatro miembros
dato. Llamamos al constructor creando un objeto de la claseVentana
Ventana ventana=new Ventana(0, 0, 20, 30);
Desde el
objeto ventana podemos llamar a las funciones miembro
públicas
ventana.mostrar();
ventana.cambiarDimensiones(10, 10);
ventana.mostrar();
LA CLASE
DERIVADA
Incrementamos
la funcionalidad de la clase Ventana definiendo una clase derivada
denominada VentanaTitulo.
Los objetos de dicha clase tendrán todas las características de los objetos de
la clase base, pero además tendrán un título, y se podran desplazar (se simula
el desplazamiento de una ventana con el ratón).
La clase derivada heredará los
miembros dato de la clase base y las funciones miembro, y tendrá un miembro
dato más, el título de la ventana.
public class VentanaTitulo extends Ventana{
protected String titulo;
public VentanaTitulo(int x, int y, int w, int h, String nombre) {
super(x, y, w, h);
titulo=nombre;
}
extends es la palabra reservada que indica que la clase VentanaTitulo deriva, o es una subclase, de la clase Ventana.
La primera
sentencia del constructor de la clase derivada es una llamada al constructor de
la clase base mediante la palabra reservada super.
La llamada
super(x, y, w, h);
inicializa
los cuatro miembros dato de la clase base Ventana: x, y, ancho, alto. A continuación, se
inicializa los miembros dato de la clase derivada, y se realizan las tareas de
inicialización que sean necesarias. Si no se llama explícitamente al
constructor de la clase base Java lo realiza por nosotros, llamando al
constructor por defecto si existe.
La función
miembro denominada desplazar cambia la posición de la ventana,
añadiéndoles el desplazamiento.
public void desplazar(int dx, int dy){
x+=dx;
y+=dy;
}
Redefine la
función miembro mostrar para mostrar una ventana con un
título.
public void mostrar(){
super.mostrar();
System.out.println("título : "+titulo);
}
En la clase
derivada se define una función que tiene el mismo nombre y los mismos
parámetros que la de la clase base. Se dice que redefinimos la funciónmostrar en la clase derivada. La función
miembro mostrar de la clase derivada VentanaTitulo hace una llamada a la función mostrar de la clase base Ventana, mediante
super.mostrar();
De este modo
aprovechamos el código ya escrito, y le añadimos el código que describe la
nueva funcionalidad de la ventana por ejemplo, que muestre el título.
Si nos
olvidamos de poner la palabra reservada super llamando a la funciónmostrar,
tendríamos una función recursiva. La función mostrar llamaría amostrar indefinidamente.
public void mostrar(){ //¡ojo!, función recursiva
System.out.println("título : "+titulo);
mostrar();
}
La
definición de la clase derivada VentanaTitulo,
será la siguiente.
package ventana;
public class VentanaTitulo extends Ventana{
protected String título;
public VentanaTitulo(int x, int y, int w, int h, String nombre) {
super(x, y, w, h);
titulo=nombre;
}
public void mostrar(){
super.mostrar();
System.out.println("titulo : "+titulo);
}
public void desplazar(int dx, int dy){
x+=dx;
y+=dy;
}
}
|
Objetos de la clase derivada
Creamos un
objeto ventana de la clase derivada VentanaTitulo
VentanaTitulo ventana=new VentanaTitulo(0, 0, 20, 30, "Principal");
Mostramos la
ventana con su título, llamando a la función mostrar,
redefinida en la clase derivada
ventana.mostrar();
Desde el
objeto ventana de la
clase derivada llamamos a las funciones miembro definidas en dicha clase
ventana.desplazar(4, 3);
Desde el
objeto ventana de la clase derivada podemos llamar a
las funciones miembro definidas en la clase base.
ventana.cambiarDimensiones(10, -5);
Para mostrar
la nueva ventana desplazada y cambiada de tamaño escribimos
ventana.mostrar();
No hay comentarios:
Publicar un comentario