HERENCIA
La herencia es un mecanismo que permite extender o reutilizar las
características (atributos) y las acciones (métodos) que presenta un tipo de
clase. Normalmente se utiliza para crear clases que reutilizan parte de la
definición de otra clase. Por ejemplo si en mi programa tengo una clase
Vehículo y quiero añadir una nueva clase Coche, que va a compartir mucha
información (atributos) y acciones (métodos) con la clase Vehículo, es mejor
reutilizar lo que me vale de Vehículo, en lugar que escribir desde cero la clase
Coche. Entre otras muchas ventajas nos permite reducir el número de clases y
líneas código de un programa en Java. Para indicar que una clase hereda de otra
clase hay que utilizar la palabra extends en la definición de la clase
hija. El ejemplo de Vehículo y Coche quedaría así:
public class Vehiculo {
/* ATRIBUTOS */
// Atributos de instancia
private String matricula;
private String marca;
private String modelo;
private String tipoCombustible;
private int vehiculoNumero;
/* MÉTODOS */
// Constructor de clase
public Vehiculo(String matricula, String marca, String
modelo,
String tipoCombustible)
{
this.matricula
= matricula;
this.marca
= marca;
this.modelo
= modelo;
this.tipoCombustible
= tipoCombustible;
vehiculoNumero = ++numeroVehiculo;
// Getter
y setter
public String getMatricula() {
return matricula;
}
.
.
.
}
public class Coche
extends Vehiculo {
private int numeroPuertas;
public Coche(String matricula, String marca, String modelo,
String tipoCombustible, int numeroPuertas)
{
/* Llamada al constructor del padre (Vehiculo), para inicializar
los atributos del padre (matricula, marca, modelo
y tipo de combustible). */
super(matricula,
marca, modelo, tipoCombustible);
this.numeroPuertas
= numeroPuertas;
}
public
int getNumeroPuertas() {
return numeroPuertas;
}
public void setNumeroPuertas(int numeroPuertas)
{
this.numeroPuertas
= numeroPuertas;
}
.
.
.
}
En el ejemplo anterior a la clase padre (Vehículo) de la herencia se
llama superclase y a la clase hija (Coche) se le llama subclase.
En este punto tenemos que introducir un nuevo elemento, la referencia super.
Este elemento se utiliza para acceder a los atributos y los métodos de la
superclase (Vehículo) desde la subclase (Coche).
Al heredar lo que estamos haciendo realmente es encapsular la clase
Vehículo dentro de la clase Coche, por este motivo todos los atributos y
métodos de Vehículo estarán disponibles en la clase Coche. Es equivalente a
construir una clase Coche con los siguientes atributos y métodos:
public class Coche {
/* ATRIBUTOS */
// Atributos de instancia
private String matricula;
private String marca;
private String modelo;
private String tipoCombustible;
private
int vehiculoNumero;
private
int numeroPuertas;
/* MÉTODOS */
// Constructor de clase
public Coche(String matricula, String marca, String modelo,
String tipoCombustible, int numeroPuertas)
{
this.matricula
= matricula;
this.marca
= marca;
this.modelo
= modelo;
this.tipoCombustible
= tipoCombustible;
this.numeroPuertas
= numeroPuertas;
}
// Getter
y setter
public String getMatricula() {
return matricula;
}
public void setMatricula(String
matricula) {
this.matricula
= matricula;
}
.
.
.
public
int getNumeroPuertas() {
return numeroPuertas;
}
public void setNumeroPuertas(int numeroPuertas)
{
this.numeroPuertas
= numeroPuertas;
}
public String
mostrarCaracteristicas() {
String caracteristicas = "Soy un vehiculo [matricula = " +
matricula + ", marca = " + marca + ",
modelo = " + modelo + ", combustible =
" + tipoCombustible + "] y soy de tipo
coche [numeroPuertas = " +
numeroPuertas + "]";
return caracteristicas;
}
}
Ahora imagine que también necesita crear nuevas clases que sean una
especialización de Vehículo o de Coche: Moto, Mono-volumen, Deportivo, etc.
Imagina la cantidad de código que tendría que repetir en cada una de estas
clases. Como puede observar la herencia nos ahorra mucho trabajo a la hora de
crear nuevas clases similares a clases de las que ya disponemos.
INTERFACES
Un interfaz es una colección de declaraciones de métodos (sin
definir el código que se ejecutará en su interior). En esta declaración se
indica el nombre del método, el valor devuelto por el método y los parámetros
que recibe. Obliga a una clase concreta a definir, a la fuerza, una serie de
métodos que son interesantes para que otra clase pueda utilizar esta clase con
los métodos definidos en la interfaz. Es un mecanismo que asegura que varias
clases puedan comunicarse entre sí. Permite definir un protocolo de comunicación
entre clases. Por ejemplo imagina que queremos crear un juego de coches y nos
interesa que cualquier coche de nuestro juego sea capaz de realizar las
acciones de arrancar, parar, girar al centro, girar a la izquierda, girar a la
derecha, acelerar, frenar y mover, entonces deberíamos crear la siguiente
interfaz:
public
interface IDesplazable {
// Métodos que nos interesa que cualquier Coche pueda
realizar
void arrancar();
void parar();
void girarAlCentro();
void girarAIzquierda();
void girarADerecha();
void acelerar();
void frenar();
void mover();
}
Y la clase que implementa esta interfaz debería de indicarlo en su
definición e implementar el contenido de estos métodos. Para indicar que una
clase va a concretizar todos estos métodos, tenemos que utilizar la palabra implements
en la declaración de la clase:
public class Coche
implements IDesplazable {
private String marca;
.
.
.
@Override
public void arrancar()
{
this.velocidad
= 1;
}
@Override
public void parar() {
velocidad = 0;
}
@Override
public void girarAlCentro() {
this.orientacion
= Orientacion.CENTRO;
}
@Override
public void girarAIzquierda() {
this.orientacion
= Orientacion.IZQUIERDA;
}
@Override
public void girarADerecha() {
this.orientacion
= Orientacion.DERECHA;
}
@Override
public void acelerar() {
velocidad++;
}
@Override
public void frenar() {
if (velocidad
!= 0)
velocidad--;
}
@Override
public void mover()
{
switch (orientacion) {
case CENTRO:
posicionY += velocidad;
break;
case IZQUIERDA:
posicionX = posicionX - velocidad;
break;
case DERECHA:
posicionX += velocidad;
break;
default:
break;
}
}
La instrucción (anotación) @Override simplemente indica
al compilador de Java que la clase Coche está dando una implementación concreta
a cada uno de estos métodos, que en la interfaz están vacios. Se podría
eliminar esta anotación y el código seguirá funcionando correctamente.