Interfaces¶
Una interfaz es un archivo .java
formado por un conjunto de métodos abstractos. Además, puede contener un conjunto de constantes públicas. Podemos considerar una interfaz como una clase abstracta pura: todos sus métodos son abstractos y, si tiene atributos, son todos constantes. En Java una interfaz se crea de forma similar a como se crea una clase utilizando la palabra clave interface en lugar de class
.
[public] interface NombreInterface{
declaraciones de métodos abstractos;
[atributos constantes;]
}
Lo que aparece entre corchetes es opcional. La interfaz puede definirse public
o sin modificador de acceso, y tiene el mismo significado que para las clases. Si tiene el modificador public
el archivo .java que la contiene debe tener el mismo nombre que la interfaz. Igual que las clases, al compilar el archivo .java de la interfaz se genera un archivo .class. Todos los métodos de una interface son públicos y abstractos, aunque no se indique explícitamente. Por lo tanto, no es necesario escribir en cada momento public abstract
. Una interfaz puede contener atributos constantes. Las constantes declaradas son públicas y estáticas, aunque no se indique explícitamente. Por lo tanto, se pueden omitir los modificadores public static final cuando se declara el atributo. Las constantes se deben inicializar en la misma instrucción de declaración.
clase abstracta vs interfaz
- En la interfaz todo método es abstracto y público sin necesidad de declararlo, mientras que una clase abstracta puede tener métodos abstractos y no abstractos.
- Los atributos declarados en una interfaz son
public static final
. Por el contrario, una clase abstracta puede contener también atributos de otro tipo (de instancia, no constantes, private, etc). - Las interfaces juegan un papel fundamental en la creación de aplicaciones Java ya que permiten interactuar a objetos no relacionados entre sí. Utilizando interfaces es posible que clases no relacionadas, situadas en distintas jerarquías de clases sin relaciones de herencia, tengan comportamientos comunes.
Las interfaces definen un protocolo de comportamiento y proporcionan un formato común para implementarlo en las clases. Los nombres de las interfaces suelen acabar en able aunque no es necesario: configurable, arrancable, dibujable, etc.
import java.util.Arrays;
public class EjemploInterface {
public static void main(String[] args) {
Jugador [] jugadores= new Jugador[7]; //array de objetos Jugador
jugadores[0] = new Jugador("Gasol", "pivot", 37);
jugadores[1] = new Jugador("Rubio", "base", 32);
jugadores[2] = new Jugador("Rodriguez", "base", 36);
jugadores[3] = new Jugador("Hernangomez", "pivot", 28);
jugadores[4] = new Jugador("Abrines", "escolta/alero", 29);
jugadores[5] = new Jugador("Aguilar", "ala-pivot", 32);
jugadores[6] = new Jugador("Oriola", "ala-pivot", 29);
Arrays.sort(jugadores);
for(Jugador j: jugadores){
System.out.println(j);
}
}
}
class Jugador implements Comparable{
private String apellido;
private String puesto;
private int edad;
public Jugador(String apellido, String puesto, int edad){
this.apellido = apellido;
this.puesto = puesto;
this.edad = edad;
}
public String getApellido() { return apellido; }
public String getPuesto() { return puesto; }
public int getEdad() { return edad; }
public void setApellido(String apellido) { this.apellido = apellido; }
public void setPuesto(String puesto) { this.puesto = puesto; }
public void setEdad(int edad) { this.edad = edad; }
@Override
public String toString(){
return "Apellido: " + apellido + " Puesto: " + puesto + " Edad: " + edad + " años."; }
public int compareTo(Object o){
Jugador auxJugador = (Jugador) o; //se realiza downcasting
if(this.edadauxJugador.edad){
return 1;
}else{
return 0;
}
}
}
El método sort()
(según se expresa en la Documentación API) requiere que todos los elementos del array implementen la interfaz Comparable
. Esta interfaz tiene el método abstracto compareTo(Object o)
que deberá ser implementado en la clase a la que pertenecen los objetos a comparar.
El método compareTo(Object o)
deberá devolver -1, 0 ó 1 en función de si la edad del primer jugador es menor, igual o mayor que la del segundo, respectivamente.
Implementando una interfaz¶
Para indicar que una clase implementa los métodos de una interfaz se utiliza la palabra clave implements
. Las clases que implementan una interfaz deben implementar todos los métodos abstractos contenidos en la interfaz. De lo contrario, serán clases abstractas y deberán declararse como tal.
A tener en cuenta
Si una clase implementa una interfaz, todas sus clases derivadas heredan los métodos implementados en la clase base y las constantes definidas en la interfaz.
Una clase puede implementar más de una interfaz. En este caso, los nombres de las interfaces se escriben a continuación de implements y separadas por comas:
public class UnaClase implements NombreInterface1, NombreInterface2, ...
Java y herencia múltiple
El lenguaje Java no permite herencia múltiple, pero las interfaces proporcionan una alternativa para implementar algo parecido a la herencia múltiple de otros lenguajes. En Java una clase solo puede tener una clase base pero puede implementar múltiples interfaces.
public class ClaseDerivada extends ClaseBase implements Interface1, Interface2, Interface3, …
Cuando hay una implementación múltiple, es posible que dos interfaces tengan atributos o métodos con el mismo nombre. La clase que implementa las interfaces recibirá métodos o atributos con el mismo nombre. A esto se le llama colisión. Java establece una serie de reglas para solucionar las colisiones. Para las colisiones de nombres de atributos se obliga a especificar el nombre de la interfaz base a la que pertenecen al utilizarlos:
NombreInterfaz.atributo;
- Si tiene el mismo nombre y diferentes parámetros se produce sobrecarga de métodos, permitiéndose que existan varias maneras de llamar al método.
- Si solo cambia el valor devuelto, da un error de compilación indicando que no se pueden implementar los dos.
- Si coinciden en sus declaraciones, se debe eliminar uno de los dos.
Se puede establecer una jerarquía de herencia entre interfaces, igual que con las clases.
public interface Interface2 extends Interface1{ …}
public interface Interface3 extends Interface1{ …}
La definición de una interfaz implica una definición de un nuevo tipo de referencia y por ello se puede usar el nombre de la interfaz como nombre de tipo. El nombre de una interfaz se puede utilizar en cualquier lugar donde pueda aparecer el nombre de un tipo de datos. Si se define una variable cuyo tipo es una interfaz, se le puede asignar un objeto que sea una instancia de una clase que implementa la interfaz.
Relacionable r1 = new Linea(2,2,4,1);
Relacionable r2 = new Fraccion(4,7);
System.out.println(r1); //ejecuta toString de Línea
System.out.println(r2); //ejecuta toString de Fracción
Relacionable [] array = new Relacionable[3];
array[0] = new Línea(2,2,4,1);
array[1] = new Fracción(4,7);
array[2] = new Línea(14,3,22,1);
for(Relacionable r: array)
System.out.println(r);
En este caso dos clases no relacionadas, Linea
y Fraccion
, por implementar la misma interfaz Relacionable
podemos manejarlas a través de referencias a la interfaz y aplicar polimorfismo. Las interfaces proporcionan más polimorfismo que el que se puede obtener de una simple jerarquía de clases.

Actividades¶
-
AC 712 (RA7/ CE7a CE7b CE7c CE7d CE7e CE7f CE7g CE7h CE7i CE7j / IC1 / 3p) Crea tres clases:
Circulo
,Cuadrado
yTrianguloEquilatero
, tendrán un atributo cada clase que permite calcular el perímetro o área (ya sea lado o radio). Crea una interfaz llamadaShapeOperable
que cada clase deberá implementar para seguir una estandarización con métodos de cálculo de perímetro y área y la constante PI.Desarrolla un
main
que pida al usuario seleccionar la forma y luego una dimensión (lado o radio). Utilizando el polimorfismo, el programa usará la instancia correcta de la forma seleccionada e imprimirá la forma seleccionada por el usuario y luego le preguntará que cálculo desea realizar si perímetro o área e imprimirá el resultado. -
AC 713 (RA7/ CE7a CE7b CE7c CE7d CE7e CE7f CE7g CE7h CE7i CE7j / IC1 / 3p). Escribe un programa llamado
Herencia3
para una biblioteca que contenga libros y revistas. En primer lugar, para prevenir posibles cambios en el programa se tiene que implementar una interfazPrestable
con los métodosprestar
ydevolver
, sin valor de retorno, y prestado quien retorna unbooleano
. La claseLibro
implementará esta interfaz.Será necesario crear la clase base
Publicación
, de la que heredarán las clasesLibro
yRevista
. Las características comunes que se almacenan tanto para las revistas como para los libros son el código, el titulo y el año de publicación. Estas tres características se pasan por parámetro en el momento de crear los objetos.Los libros tienen además un atributo
prestado
. Los libros cuando se crean no están prestados.Las revistas tienen un número. En el momento de crearlas se pasa el número por parámetro.
Tanto las revistas como los libros deben de tener (aparte de los constructores) un método
toString
que devuelve el valor de todos los atributos en una cadena de caracteres. También tienen un método que devuelve el año de publicación y otro para el código. -
PR 714 (RA7/ CE7a CE7b CE7c CE7d CE7e CE7f CE7g CE7h CE7i CE7j / IC2 / 10p). Se pretende realizar una aplicación para una facultad que gestione la información sobre las personas vinculadas con la misma, que se pueden clasificar en tres tipos: estudiantes, profesores y personal de servicio.
-
1) A continuación, se detalla qué tipo de información debe gestionar esta aplicación:
- Por cada persona, se debe conocer, al menos, su nombre y apellidos, su número de identificación y su estado civil.
- Con respecto a los empleados, sean del tipo que sean, hay que saber su año de incorporación a la facultad y qué número de despacho tienen asignado.
- En cuanto a los estudiantes, se requiere almacenar el curso en el que están matriculados.
- Por lo que se refiere a los profesores, es necesario gestionar a qué departamento pertenecen (lenguajes, matemáticas, arquitectura, ...).
- Sobre el personal de servicio, hay que conocer a qué sección están asignados (biblioteca, decanato, secretaría, ...).
-
2) Seguidamente se debe programar las clases definidas en las que, además de los constructores, hay que desarrollar los métodos correspondientes a las siguientes acciones:
- Cambio del estado civil de una persona.
- Reasignación de despacho a un empleado.
- Matriculación de un estudiante en un nuevo curso.
- Cambio de departamento de un profesor.
- Traslado de sección de un empleado del personal de servicio.
- Imprimir toda la información de cada tipo de individuo.
Llegados a este punto, incluye un programa de prueba que instancie objetos de los distintos tipos y pruebe los métodos desarrollados.
-
3) Una vez comprobado lo anterior, se plantea extender el punto anterior incluyendo una clase que represente al centro docente. Esa clase incluirá 3 contenedores, uno por cada tipo de persona vinculada con el centro. En una primera fase deben incluirse los siguiente métodos:
- Uno para dar de alta una persona, que incoporará a la persona en la lista correspondiente.
- Otro para dar de baja una persona, dado su DNI. Añada un método a la clase persona para poder obtener el DNI de un objeto de esa clase.
- Uno último para imprimir toda la información de las personas vinculadas con el centro.
Piensa primero
Dado que hay múltiples altenativas a la hora de afrontar este problema, a continuación, se explican las características de la solución implementada, aunque el alumno podrá realizar el diseño que considere oportuno:
- El método de alta recibe como parámetro un objeto del tipo persona correspondiente, existiendo, por tanto, tres versiones sobrecargadas del mismo.
- Se ha de usar array de objetos.
El método de baja busca, en primer lugar, un objeto en las listas que tenga el DNI recibido como parámetro. Una vez encontrado, lo inicializa a 0.
Ten en cuenta
Guarda la versión anterior y realiza este ejercicio sobre una copia de la misma, puesto que dicha versión previa será utilizada en ejercicios posteriores.
-
4) En la aplicación anterior, se detecta que en el futuro se va a necesitar crear nuevos tipos de empleados (por ejemplo, investigadores) y distinguir entre distintos tipos de estudiantes. Por tanto, para que el diseño se pueda adaptar a estas necesidades futuras, se plantea unificar todos los contenedores del tipo centro, de manera que sólo haya un único contenedor de personas, y usar polimorfismo para gestionar los distintos tipos de personas.
Modifica el programa anterior para adaptarlo a este nuevo diseño. Ten en cuenta que debe desaparecer cualquier referencia a profesores, personal de servicio y estudiantes en el código de la clase que representa al centro. Asimismo, haz que las clases que corresponden a personas y empleados sean abstractas.
Entrega
Esta parte se diferenceciará del anterior con la nomenclatura
XXXXXXXAlt.java
, haciendo referencia a una versión alternativa. -
5) En la versión correspondiente al tercer punto, se va a añadir un nuevo método a las clases profesor y personal de servicio para calcular su salario. Se va a suponer que la forma de calcular el salario para estos dos tipos de empleados es totalmente distinta y que no se puede sacar ningún código común para incluirlo en la clase empleado. Haga la suposición que considere oportuna sobre cómo calcular el sueldo de cada tipo de empleado, dado que no es importante para el ejemplo.
Una propuesta
Aquí va una propuesta bastante ridícula: el personal de servicio cobra una cantidad fija más un 5% si están casados; el personal docente gana un fijo más un 8% si su fecha de incorporación es anterior al 2000. Habilite los métodos en la clase base que necesite para obtener los datos que requiera para el cálculo del sueldo.
Una vez añadidos los métodos para calcular el salario en cada una de las dos clases, debe añadir un método en la clase que representa el centro que imprima el salario de todos los empleados del centro (nombre y apellidos más el sueldo).
-
6) Se plantea mejorar las clases diseñadas hasta ahora en los siguientes aspectos:
- Añadir una operación leer en cada clase persona para leer los datos de la clase.
- Sobrecargar el operador constructor para que lea los datos de cada clase persona.
- Polimorfismo en el operador toString para que imprima los datos del centro.
-
7) Hagamos algunas mejoras adicionales en la aplicación desarrollada. Haz que el programa principal dialoge con el usuario pidiéndolo qué tipo de operación quiere llevar a cabo (alta, baja, imprimir listado o imprimir nóminas) y vaya pidiendo los datos que necesite para llevar a cabo la operación.
-
-
PR 715 (RA7/ CE7a CE7b CE7c CE7d CE7e CE7f CE7g CE7h CE7i CE7j / IC2 / 5p). Realiza un programa de nombre
AppAnimal
formado por los siguientes elementos:- Clase
Animal
, con el atributoprotected
nombre
de tipoString
, y los métodos abstractoscomer
sin valor de retorno y al que se le pasa como parámetro elString
alimento mostrando la siguiente línea “El [nombre_animal] come alimento.”, ynacer
que devuelve unString
(vivíparos u ovíparos). - Interfaz
Alimentable
, con un métodosegunAlimento
al que se le pasa elString
alimento y devuelve unString
indicando si el animal es carnívoro, omnívoro u herbívoro. - Clase
Mamifero
que hereda deAnimal
, e implementa los métodoscomer
ynacer
, y la interfazAlimentable
. - En el
main
de la claseAppAnimal
:- Crea un objeto
Mamifero
m. - Solicita al usuario el nombre del mamífero.
- Pide al usuario que indique la alimentación del mamífero.
- Invoca al método comer.
- Invoca al método segunAlimento.
- Invoca al método nacer.
- Crea un objeto
- Clase