Herencia

Anuncio
10 -Herencia Y Polimorfismo
Programación Orientada a Objetos
Proyecto Curricular de Ingeniería de Sistemas
Herencia
Si se supone que somos buenos programando, cuando creemos una clase es posible que sea algo
útil. De modo que cuando estemos haciendo un programa distinto y necesitemos esa clase
podremos incluirla en el código de ese nuevo programa. Es la manera más sencilla de reutilizar
una clase.
También es posible que utilicemos esa clase incluyendo instancias de la misma en nuevas
clases. A eso se le llama composición. Representa una relación "tiene un". Es decir, si tenemos
una clase Rueda y una clase Coche, es de esperar que la clase Coche tenga cuatro instancias
de Rueda:
class Coche {
Rueda rueda1, rueda2, rueda3, rueda 4;
...
}
Sin embargo, en ocasiones, necesitamos una relación entre clases algo más estrecha. Una
relación del tipo "es un". Por ejemplo, sabemos bien que un gato es un mamífero. Sin embargo
es también un concepto más específico, lo que significa que una clase Gato puede compartir
con Mamifero propiedades y métodos, pero también puede tener algunas propias.
Herencia.java
class Mamifero {
String especie, color;
}
class Gato extends Mamifero {
int numero_patas;
}
public class Herencia {
public static void main(String[] args) {
Gato bisho;
bisho = new Gato();
bisho.numero_patas = 4;
bisho.color = "Negro";
System.out.println(bisho.color);
}
}
Como vemos en el ejemplo, el objeto bisho no sólo tiene la propiedad numero_patas,
también color que es una propiedad de Mamifero. Se dice que Mamifero es la clase padre y
Gato la clase hija en una relación de herencia. Esta relación se consigue en Java por medio de
la palabra reservada extends.
Pero, además de heredad la funcionalidad de la clase padre, una clase hija puede sobreescribirla.
Podemos escribir un método en la clase hija que tenga el mismo nombre y los mismos
parámetros que un método de la clase padre:
Herencia.java
class Mamifero {
String especie, color;
public void mover() {
System.out.println("El mamífero se mueve");
}
}
class Gato extends Mamifero {
int numero_patas;
public void mover() {
System.out.println("El gato es el que se mueve");
}
}
public class Herencia {
public static void main(String[] args) {
Gato bisho = new Gato();
bisho.mover();
}
}
Al ejecutar esta nueva versión veremos que se escribe el mensaje de la clase hija, no el del
padre.
Conviene indicar que Java es una lenguaje en el que todas las clases son heredadas, aún cuando
no se indique explícitamente. Hay una jerarquía de objetos única, lo que significa que existe una
clase de la cual son hijas todas las demás. Este Adán se llama Object y, cuando no indicamos
que nuestras clases hereden de nadie, heredan de él. Esto permite que todas las clases tengan
algunas cosas en común, lo que permite que funcione, entre otras cosas, el recolector de basura.
Polimorfismo
En muchas ocasiones, cuando utilizamos herencia podemos terminar teniendo una familia de
clases que comparten un interfaz común. Por ejemplo, si creamos un nuevo fichero que
contenga a Mamifero y Gato le añadimos:
Polimorfismo.java
class Perro extends Mamifero {
int numero_patas;
public void mover() {
System.out.println("Ahora es un perro el que se mueve");
}
}
public class Polimorfismo {
public static void muevete(Mamifero m) {
m.mover();
}
public static void main(String[] args) {
Gato bisho = new Gato();
Perro feo = new Perro();
muevete(bisho);
muevete(feo);
}
}
Vemos que el método muevete llama al método mover de un mamífero. El no sabe con qué
clase de mamífero trata, pero la cosa funciona y se llama al método correspondiente al objeto
específico que lo llama (es decir, primero un gato y luego un perro). Y esto no sólo se aplica a
los métodos. Por ejemplo, podemos reescribir el código del procedimiento principal:
public static void main(String[] args) {
Mamifero bisho = new Gato();
muevete(bisho);
bisho = new Perro();
muevete(bisho);
}
Y vemos que funciona exactamente igual. El polimorfismo consiste en que toda referencia a un
objeto de una clase específica puede tomar la forma de una referencia a un objeto de una clase
heredada a la suya.
Sobrecarga de métodos
El concepto de polimorfismo, en cuanto a cambio de forma, se puede extender a los métodos.
Java permite que varios métodos dentro de una clase se llamen igual, siempre y cuando su lista
de parámetros sea distinta. Por ejemplo, si tuviéramos un método que sirviera para sumar
números pero sin indicar de qué tipo:
Sumar.java
/** Diversos modos de sumar */
public class Sumar {
public float suma(float a, float b) {
System.out.println("Estoy sumando reales");
return a+b;
}
public int suma(int a, int b) {
System.out.println("Estoy sumando enteros");
return a+b;
}
public static void main(String[] args) {
float x = 1, float y = 2;
int v = 3, int w = 5;
System.out.println(suma(x,y));
System.out.println(suma(v,w));
}
}
Esto también se aplica a los constructores. De hecho, es la aplicación más habitual de la
sobrecarga:
Rectangulo.java
/** Calcula el area de un rectangulo
*/
public class Rectangulo {
private float x1,y1,x2,y2;
public Rectangulo(float ex1, float ey1, float ex2, float ey2)
{
x1 = ex1;
x2 = ex2;
y1 = ey1;
y2 = ey2;
}
public Rectangulo() {
x1 = 0;
x2 = 0;
y1 = 1;
y2 = 1;
}
public float calcularArea() {
return (x2-x1) * (y2-y1);
}
public static void main(String[] args) {
Rectangulo prueba1 = new Rectangulo(1,4,7,6);
Rectangulo prueba2 = new Rectangulo();
System.out.println(prueba1.calcularArea());
System.out.println(prueba2.calcularArea());
}
}
Descargar