Está en la página 1de 10

Clases abstractas

Una clase que declara la existencia de m�todos pero no la implementaci�n de dichos


m�todos (o sea, las llaves { } y las sentencias entre ellas), se considera una
clase abstracta.

Una clase abstracta puede contener m�todos no-abstractos pero al menos uno de los
m�todos debe ser declarado abstracto.

Para declarar una clase o un metodo como abstractos, se utiliza la palabra


reservada abstract.

abstract class Drawing


{
abstract void miMetodo(int var1, int var2);
String miOtroMetodo( ){ ... }
}

Una clase abstracta no se puede instanciar pero si se puede heredar y las clases
hijas ser�n las encargadas de agregar la funcionalidad a los m�todos abstractos. Si
no lo hacen as�, las clases hijas deben ser tambi�n abstractas.

**Clases Abstractas en Java**

abstract class Ejemplo{


abstract miMetodo();
}

Estudiemos pues este sencillo ejemplo:

1. Para empezar identificamos la clase abstracta con la palabra reservada abstract.

2. Esta clase abstracta tiene un m�todo abstracto. Por cierto, este no tiene body.
Eso es porque los m�todos abstractos no necesitan cuerpo.

�Y entonces para que nos sirven las clases abstractas? Las clases abstractas
cumplen una funci�n muy especial� S�lo sirven para la herencia. Otro detalle: No se
pueden instanciar, jamas, es imposible encontrar un objeto de las clases Ejemplo y
OtroEjemplo.

Vamos entrando en detalle�

Clase Animal:
abstract class Animal{
public abstract void habla();
}

Clase Perro:
class Perro extends Animal{
public void habla(){
System.out.println("Guau, guau!");
}
}

y la clase Gato:
class Gato extends Animal{
public void habla(){
System.out.println("Miau, miau!");
}
}

Este ejemplo es mucho m�s claro� Sabemos que todos los animales hablan, pero no
todos lo hacen de la misma forma� Por eso heredamos de la clase Animal el m�todo
abstracto habla y lo implementamos en las clases Perro y Gato� �Qu� pasa si�?
class Gato extends Animal{
public void hablaGato(){
System.out.println("Miau, miau");
}
}

Este c�digo es totalmente incorrecto. Siempre que una clase hereda de una clase
abstracta est� obligada a usar un m�todo con el mismo nombre, pero esta vez con
sentencias dentro de las {llaves}.
Vamos m�s adentro� .
public class Eject{
public static void main(String... args){
Animal donGato = new Gato();
Animal benitoBodoque = new Gato();
}
}

Hasta este momento el c�digo es correcto. Estamos creando una referencia de la


clase abstracta Animal. Pero recordemos, no podemos generar un objeto de tipo
Animal. Sin embargo, podemos con la referencia de la clase Animal crear un objeto
de la clase Gato o de la clase Perro.

Y en Java esas son las clases abstractas�

Interfaces

Un interfaz es una lista de acciones que puede llevar a cabo un determinado objeto.
Sorpresa, �eso no eran los m�todos que se definen en una clase? Casi, en una clase
adem�s de aparecer los m�todos aparec�a el c�digo para dichos m�todos, en cambio en
un interfaz s�lo existe el prototipo de una funci�n, no su c�digo.

Ve�moslo con un ejemplo: Pensemos en un interfaz en el que en su lista de m�todos


aparecen los m�todos despegar, aterrizar, servirComida y volar. Todos pensamos en
un avi�n, �verdad? El motivo es sencillamente que avi�n es el concepto que engloba
las acciones que hemos detallado antes, a pesar que existan muchos objetos avi�n
diferentes entre s�, por ejemplo Boeing 747, Boeing 737, MacDonell-Douglas.

Lo realmente interesante es que todos ellos, a pesar de pertenecer a clases


distintas, poseen el interfaz avi�n, es decir poseen los m�todos detallados en la
lista del interfaz avi�n.

Esto significa tambi�n que a cualquier avi�n le podemos pedir que vuele, sin
importarnos a que clase real pertenezca el avi�n, evidentemente cada clase
especificar� como volar� el avi�n (porque proporciona el c�digo de la funci�n
volar).

En java un interfaz define la lista de m�todos, pero para que una clase posea un
interfaz hay que indicar expl�citamente que lo implementa mediante la cla�sula
implements. Pero veamos primero la estructura de un interfaz:
[modif.visibilidad] interface nombreInterfaz [extends listaInterfaces]

prototipo m�todo1;

.....

prototipo m�todo1;

Donde modif.visibilidad puede ser public o bien sin especificar, es decir


visibilidad p�blica (desde cualquier clase se puede emplear el interfaz) o de
paquete (s�lo se puede emplear desde clases del mismo paquete).

nombreInterfaz por convenio, sigue las mismas reglas de nomenclatura que las
clases, y en muchos casos acaba en able (que pod�amos traducir como: 'ser capaz
de').

La cla�sula opcional extends, se emplea para conseguir que un interfaz herede las
funciones de otro/s interfaces, simplemente listaInterfaces es una lista separada
por coma de interfaces de los que se desea heredar.

En muchas ocasiones un interfaz es empleado para definir un comportamiento, que


posteriormente ser� implementado por diversas clases, que podr�n no tener nada que
ver entre ellas, pero que todas se comportar�n igual de cara al interfaz. Es decir,
todas tendr�n las funciones indicadas por el interfaz.

Cuando varios objetos de distintas clases pueden responder al mismo mensaje


(funci�n), a�n realizando cosas distintas se denomina polimorfismo.

Pr�cticas:

Vamos a definir el interfaz Cantante, un interfaz muy simple que s�lo posee un
m�todo: cantar.

Crear el fichero Cantante.java

Agregar el siguiente c�digo:

public interface Cantante

public void cantar();


}

Cojamos la clase Persona y hagamos que implemente el interfaz Cantante:

public class Persona implements Cantante

Adem�s agreguemos el c�digo para el m�todo que define el interfaz cantante:

public void cantar()

{
System.out.println("La laa la raa laaa!");

Construyamos ahora una clase con funci�n main (ArranqueInterfaz.java)para ejecutar:

public class ArranqueInterfaz

public static void main(String arg[])

Persona p = new Persona();

hacerCantar(p);

public static void hacerCantar(Cantante c)

c.cantar();

Podemos ver que construimos un objeto (p) de tipo persona y se lo pasamos a la


funci�n hacerCantar. Esta funci�n espera recibir un objeto Cantante, y una persona
lo es, por tanto la recibe y llama al m�todo cantar del objeto recibido.

Probemos a intentar pasar a la funci�n hacerCantar en lugar del objeto Persona (p)
un objeto String (texto), resultado: error de compilaci�n.

Contruyamos ahora la clase Canario (Canario.java), pensando que tambi�n sabe


cantar:

public class Canario implements Cantante

private int peso;

/* Aqui vendr�an el resto de atributos y funciones propias de un canario */

public void cantar()

System.out.println("Pio Pio Pio");

}
Y ahora agreguemos en la clase ArranqueInterfaz el siguiente c�digo, para crear un
objeto canario y pasarselo a la funci�n hacerCantar:

Canario c = new Canario();

hacerCantar(c);

Tras ejecutar comprobaremos que podemos pasar tanto una Persona como un Canario a
la funci�n hacerCantar, de tal manera que dentro de dicha funci�n s�lo accedamos a
las funciones del interfaz y no habr� problemas. Por ejemplo, si pusi�ramos:

c.SetNombre("Luis")

dentro de la funci�n hacerPersona, podr�a funcionar si pas�semos un objeto Persona,


pero no si pasamos uno de tipo Canario.

****Interfaces en Java.*****

Los m�todos abstractos son �tiles cuando se quiere que cada implementaci�n de la
clase parezca y funcione igual, pero necesita que se cree una nueva clase para
utilizar los m�todos abstractos. Los interfaces proporcionan un mecanismo para
abstraer los m�todos a un nivel superior, lo que permite simular la herencia
m�ltiple de otros lenguajes.
Un interfaz sublima el concepto de clase abstracta hasta su grado m�s alto. Un
interfaz podr� verse simplemente como una forma, es como un molde, solamente
permite declarar nombres de m�todos, listas de argumentos, tipos de retorno y
adicionalmente miembros datos (los cuales podr�n ser �nicamente tipos b�sicos y
ser�n tomados como constantes en tiempo de compilaci�n, es decir, static y final).
Un interfaz contiene una colecci�n de m�todos que se implementan en otro lugar. Los
m�todos de una clase son public, static y final.
La principal diferencia entre interface y abstract es que un interfaz proporciona
un mecanismo de encapsulaci�n de los protocolos de los m�todos sin forzar al
usuario a utilizar la herencia. Por ejemplo:
public interface VideoClip {
// comienza la reproduccion del video
void play();
// reproduce el clip en un bucle
void bucle();
// detiene la reproduccion
void stop();
}
Las clases que quieran utilizar el interfaz VideoClip utilizar�n la palabra
implements y proporcionar�n el c�digo necesario para implementar los m�todos que se
han definido para el interfaz:
class MiClase implements VideoClip {
void play() {
<c�digo>
}
void bucle() {
<c�digo>
}
void stop() {
<c�digo>
}
Al utilizar implements para el interface es como si se hiciese una acci�n de
copiar-y-pegar del c�digo del interface, con lo cual no se hereda nada, solamente
se pueden usar los m�todos.
La ventaja principal del uso de interfaces es que una clase interface puede ser
implementada por cualquier n�mero de clases, permitiendo a cada clase compartir el
interfaz de programaci�n sin tener que ser consciente de la implementaci�n que
hagan las otras clases que implementen el interface.
class MiOtraClase implements VideoClip {
void play() {
<c�digo nuevo>
}
void bucle() {
<c�digo nuevo>
}
void stop() {
<c�digo nuevo>
}
Es decir, el aspecto m�s importante del uso de interfaces es que m�ltiples objetos
de clases diferentes pueden ser tratados como si fuesen de un mismo tipo com�n,
donde este tipo viene indicado por el nombre del interfaz.
Aunque se puede considerar el nombre del interfaz como un tipo de prototipo de
referencia a objetos, no se pueden instanciar objetos en s� del tipo interfaz. La
definici�n de un interfaz no tiene constructor, por lo que no es posible invocar el
operador new sobre un tipo interfaz.
Un interfaz puede heredar de varios interfaces sin ning�n problema. Sin embargo,
una clase solamente puede heredar de una clase base, pero puede implementar varios
interfaces. Tambi�n, el JDK ofrece la posibilidad de definir un interfaz vac�o,
como es el caso de Serialize, que permite serializar un objeto. Un interfaz vac�o
se puede utilizar como un flag, un marcador para marcar a una clase con una
propiedad determinada.
La aplicaci�n java514.java, ilustra algunos de los conceptos referentes a los
interfaces. Se definen dos interfaces, en uno de ellos se definen dos constantes y
en el otro se declara un m�todo put() y un m�todo get(). Las constantes y los
m�todos se podr�an haber colocado en la misma definici�n del interfaz, pero se han
separado para mostrar que una clase simple puede implementar dos o m�s interfaces
utilizando el separador coma (,) en la lista de interfaces.
Tambi�n se definen dos clases, implementando cada una de ellas los dos interfaces.
Esto significa que cada clase define el m�todo put() y el m�todo get(), declarados
en un interfaz y hace uso de las constantes definidas en el otro interfaz. Estas
clase se encuentran en ficheros separados por exigencias del compilador, los
ficheros son Constantes.java y MiInterfaz.java, y el contenido de ambos ficheros es
el que se muestra a continuaci�n:
public interface Constantes {
public final double pi = 6.14;
public final int constanteInt = 125;
}

public interface MiInterfaz {


void put( int dato );
int get();
}
Es importante observar que en la definici�n de los dos m�todos del interfaz, cada
clase los define de la forma m�s adecuada para esa clase, sin tener en cuenta c�mo
estar� definidos en las otras clases.
Una de las clases tambi�n define el m�todo show(), que no est� declarado en el
interfaz. Este m�todo se utiliza para demostrar que un m�todo que no est� declarado
en el interfaz no puede ser accedido utilizando una variable referencia de tipo
interfaz.
El m�todo main() en la clase principal ejecuta una serie de instanciaciones,
invocaciones de m�todos y asignaciones destinadas a mostrar las caracter�sticas de
los interfaces descritos anteriormente. Si se ejecuta la aplicaci�n, las sentencias
que se van imprimiendo en pantalla son autoexplicactivas de lo que est� sucediendo
en el coraz�n de la aplicaci�n.
Los interfaces son �tiles para recoger las similitudes entre clase no relacionadas,
forzando una relaci�n entre ellas. Tambi�n para declarar m�todos que forzosamente
una o m�s clases han de implementar. Y tambi�n, para tener acceso a un objeto, para
permitir el uso de un objeto sin revelar su clase, son los llamados objetos
an�nimos, que son muy �tiles cuando se vende un paquete de clases a otros
desarrolladores.
C++ permite al programador crear nuevas clases como una subclase de dos o m�s
superclases diferentes, es la herencia m�ltiple. Java no permite herencia m�ltiple.
Hay autores que dicen que el interfaz de Java es un sustituto de la herencia
m�ltiple y hay otros que est�n en desacuerdo con eso. Lo cierto es que s� parece
una alternativa y los interfaces resuelven algunos de los problemas de la herencia
m�ltiple, por ejemplo:
No se pueden heredar variables desde un interfaz
No se pueden heredar implementaciones de m�todos desde un interfaz
La jerarqu�a de un interfaz es independiente de la jerarqu�a de clases que
implementen el mismo interfaz
y esto no es cierto en la herencia m�ltiple, tal como se ve desde C++.
Definici�n
La definici�n de un interfaz es semejante a la de una clase. La definici�n de
interfaz tiene dos componentes, declaraci�n y cuerpo. En forma esquem�tica ser�a:
DeclaracionInterfaz {
// cuerpoInterfaz
}
Declaraci�n
La m�nima declaraci�n consiste en la palabra clave interface y el nombre del
interfaz. Por convenio, los nombres de interfaces comienzan con una letra
may�scula, como los nombres de las clases, pero no es obligatorio.
La declaraci�n de interfaz puede tener dos componentes adicionales, el
especificador de acceso public y la lista de superinterfaces.
Un interfaz puede extender otros interfaces. Sin embargo, mientras que una clase
solamente puede extender otra clase, un interfaz puede extender cualquier n�mero de
interfaces. En el ejemplo se muestra la definici�n completa de un interfaz,
declaraci�n y cuerpo.
public interface MiInterfaz extends InterfazA,InterfazB {
public final double PI = 3.14159;
public final int entero = 125;
void put( int dato );
int get();
}
El especificador de acceso public indica que el interfaz puede ser utilizado por
cualquier clase de cualquier paquete. Si se omite, el interfaz solamente ser�
accesible a aquellas clases que est�n definidas en el mismo paquete.
La cl�usula extends es similar a la de la declaraci�n de clase, aunque un interfaz
puede extender m�ltiples interfaces. Un interfaz no puede extender clases.
La lista de superinterfaces es un lista separada por comas de todas las interfaces
que la nueva interfaz va a extender. Un interfaz hereda todas las constantes y
m�todos de sus superinterfaces, excepto si el interfaz oculta una constante con
otra del mismo nombre, o si redeclara un m�todo con una nueva declaraci�n de ese
m�todo.
El cuerpo del interfaz contiene las declaraciones de los m�todos, que terminan en
un punto y coma y no contienen c�digo alguno en su cuerpo. Esto es semejante al
prototipo de funciones en C++. Todos los m�todos declarados en un interfaz son
impl�citamente, public y abstract, y no se permite el uso de transient, volatile,
private, protected o syncronized en la declaraci�n de miembros en un interfaz. En
el cuerpo del interfaz se pueden definir constantes, que ser�n impl�citamente
public, static y final.
Implementaci�n
Un interfaz se utiliza definiendo una clase que implemente el interfaz a trav�s de
su nombre. Cuando una clase implementa un interfaz, debe proporcionar la definici�n
completa de todos los m�todos declarados en el interfaz y, tambi�n, la de todos los
m�todos declarados en todos los superinterfaces de ese interfaz.
Una clase puede implementar m�s de un interfaz, incluyendo varios nombre de
interfaces separados por comas. En este caso, la clase debe proporcionar la
definici�n completa de todos los m�todos declarados en todos los interfaces de la
lista y de todos los superinterfaces de esos interfaces.
En el anterior ejemplo, java514.java, se puede observar una clase que implementa
dos interfaces, Constantes y MiInterfaz.
class ClaseA implements Constantes,MiInterfaz {
double dDato;
//Define las versiones de put() y
//get() que utiliza la ClaseA
public void put( int dato ) {
// Se usa "pi" del interfaz Constantes
dDato = (double)dato * pi;
System.out.println(
"En put() de ClaseA, usando pi del interfaz " +
"Constantes: " + dDato );
}
public int get() {
return( (int)dDato );
}
// Se define un metodo show() para la ClaseA que no esta
// declarado en el interfaz MiInterfaz
void show() {
System.out.println(
"En show() de ClaseA, dDato = " + dDato );
}
}
Como se puede observar, esta clase proporciona la definici�n completa de los
m�todos put() y get() del interfaz MiInterfaz, a la vez que utiliza las constantes
definidas en el interfaz Constantes. Adem�s, la clase proporciona la definici�n del
m�todo show() que no est� declarado en ninguno de los interfaces, sino que es
propio de la clase.
La definici�n de un interfaz es una definici�n de un nuevo tipo de datos. Se puede
utilizar el nombre del interfaz en cualquier lugar en que se pueda utilizar un
nombre de tipo de dato. Sin embargo, no se pueden instanciar objetos del tipo
interfaz, porque un interfaz no tiene constructor. En esta secci�n, hay numerosos
ejemplos de uso del nombre de un interfaz como tipo.
Herencia "Multiple"
Un interfaz no es solamente una forma m�s pura de denominar a una clase abstracta,
su prop�sito es mucho m�s amplio que eso. Como un interfaz no tiene ninguna
implementaci�n, es decir, no hay ningun tipo de almacenamiento asociado al
interfaz, no hay nada que impida la combinaci�n de varios interfaces. Esto tiene
mucho valor porque hay veces en que es necesario que un objeto X sea a y b y c. En
C++ es donde esto se acu�� como herencia multiple y no es sencillo de hacer porque
cada clase puede tener su propia implementaci�n. En Java, se puede hacer lo mismo,
pero solamente una de las clases puede tener implementeaci�n, con lo cual los
problemas que se presentan en C++ no suceden con Java cuando se combinan multiples
interfaces.
En una clase derivada, el programador no est� forzado a tener una clase base sea
esta abstracta o concreta, es decir, una sin m�todos abstractos. Si se hereda desde
una clase no interfaz, solamente se puede heredar de una. El resto de los elementos
base deben ser interfaces. Todos los nombres de interfaces se colocan despu�s de la
palabra clave implements y separados por comas. Se pueden tener tantos interfaces
como se quiera y cada uno de ellos ser� un tipo independiente. El ejemplo
siguiente, java516.java, muestra una clase concreta combinada con varios interfaces
para producir una nueva clase
import java.util.*;

interface Luchar {
void luchar();
}
interface Nadar {
void nadar();
}
interface Volar {
void volar();
}
class Accion {
public void luchar() {}
}

class Heroe extends Accion implements Luchar,Nadar,Volar {


public void nadar() {}
public void volar() {}
}

public class java516 {


static void a( Luchar x ) {
x.luchar();
}
static void b( Nadar x ) {
x.nadar();
}
static void c( Volar x ) {
x.volar();
}
static void d( Accion x ) {
x.luchar();
}

public static void main( String args[] ) {


Heroe i = new Heroe();
a( i ); // Trata al Heroe como Luchar
b( i ); // Trata al Heroe como Nadar
c( i ); // Trata al Heroe como Volar
d( i ); // Trata al Heroe como Accion
}
}
Se puede observar que Heroe combina la clase concreta Accion con los interfaces
Luchar, Nadar y Volar. Cuando se combina la clase concreta con interfaces de este
modo, la clase debe ir la primera y luego los interfaces; en caso contrario, el
compilador dar� un error.
La autentificaci�n, signature, para luchar() es la misma en el interfaz Luchar y en
la clase Accion, y luchar() no est� proporcionado con la definicion de Heroe. Si se
quiere crear un objeto del nuevo tipo, la clase debe tener todas las definiciones
que necesita, y aunque Heroe no proporciona una definicion explicita para luchar(),
la definici�n es proporcionada autom�ticamente por Accion y as� es posible crear
objetos de tipo Heroe.
En la clase java516, hay cuatro m�todos que toman como argumentos los distintos
interfaces y la clase concreta. Cuando un objeto Heroe es creado, puede ser pasado
a cualquierea de estos m�todos, lo que significa que se est� realizando un
upcasting al interfaz de que se trate. Debido a la forma en que han sido dise�ados
los interfaces en Java, esto funciona perfectamente sin ninguna dificultad ni
esfuerzo extra por parte del programador.
La raz�n principal de la existencia de los interfaces en el ejemplo anterior es el
proder realizar un upcasting a m�s de un tipo base. Sin embargo, hay una segunda
raz�n que es la misma por la que se usan clases abstractas: evitar que el
programador cliente tenga que crear un objeto de esta clase y establecer que
solamente es un interfaz. Y esto plantea la cuesti�n de qu� se debe utilizar pues,
un interfaz o una clase abastacta. Un interfaz proporciona los beneficios de una
clase abstracta y, adem�s, los beneficios propios del interfaz, as� que es posible
crear una clase base sin la definici�n de ning�n m�todo o variable miembro, por lo
que se deber�an utilizar mejor los interfaces que las clases abstractas. De hecho,
si se desea tener una clase base, la primera elecci�n deber�a ser un interfaz, y
utilizar clases abstractas solamente si es necesario tener alguna variable miembro
o algun m�todo implementado.

También podría gustarte