Una interfaz es un contrato
Una interfaz declara qué puede hacer una clase sin decir cómo. Es una lista de firmas de métodos que cualquier clase que la implemente promete cumplir. La clave es el desacoplamiento: el código puede trabajar con el tipo de la interfaz sin importarle qué clase concreta hay detrás.
Circle implements Shape significa que Circle debe definir area y perimeter. Una vez que lo hace, un Circle es una Shape y puede almacenarse en una variable de tipo Shape.
Muchas clases, un solo tipo
La potencia se aprecia cuando varias clases sin relación entre sí implementan la misma interfaz. El código escrito contra Shape las maneja todas:
El bucle nunca pregunta "¿esto es un Circle o un Rectangle?" - simplemente llama a area() y confía en el contrato. Añadir un Triangle más adelante no requiere ningún cambio aquí.
Implementar múltiples interfaces
Una clase extiende solo una clase, pero puede implementar cualquier número de interfaces; así es como Java logra de forma segura la "herencia múltiple" de comportamiento:
Enumera las interfaces separadas por comas después de implements. La clase debe satisfacerlas todas.
Métodos default y static
Desde Java 8, una interfaz puede incluir cuerpos de método. Un método default da a las clases que la implementan una implementación lista para usar que heredan gratis (y pueden sobrescribir):
Los métodos default permiten que una interfaz evolucione: añadir un método sin romper a todos los implementadores existentes. Un método de interfaz static, en cambio, es una utilidad que invocas sobre la propia interfaz, como Comparator.naturalOrder().
Constantes
Los campos de una interfaz son implícitamente public static final: son constantes, no estado de instancia:
interface Physics {
double GRAVITY = 9.81; // automatically public static final
}
Las interfaces tradicionalmente no guardan estado por objeto; la ausencia de campos de instancia es parte de lo que las distingue de las clases.
Interfaces funcionales
Una interfaz con exactamente un método abstracto es una interfaz funcional, y puedes implementarla con una expresión lambda en lugar de toda una clase:
Esta es la base de los lambdas de Java y de los tipos de java.util.function (Function, Predicate, Supplier y compañía). La anotación @FunctionalInterface hace explícita la intención y permite que el compilador imponga la regla de un solo método.
Interfaz frente a clase abstracta
Ambas te permiten programar contra una abstracción, así que ¿cuándo eliges cada una?
- Interfaz - una capacidad que clases sin relación entre sí pueden compartir. Un
Birdy unAirplanepueden ser ambosFlyable. Una clase puede implementar muchas. Sin estado de instancia. - Clase abstracta - estado y código compartidos entre clases estrechamente relacionadas. Un
Caty unDogambos extiendenAnimal, heredando campos comunes y métodos parcialmente implementados. Una clase extiende solo una.
Un patrón habitual las combina: una interfaz define el contrato y una clase abstracta implementa las partes repetitivas, de modo que las subclases concretas solo rellenan los detalles específicos.
Siguiente: clases abstractas
Las interfaces definen comportamiento sin estado. Las clases abstractas se sitúan a medio camino entre las interfaces y las clases completas: pueden declarar métodos sin implementar y además llevar campos y constructores. Ese es el tema de la siguiente página.
Preguntas frecuentes
¿Qué es una interfaz en Java?
Una interfaz es un contrato: un conjunto de firmas de métodos (y constantes) que una clase promete proporcionar. Indica qué puede hacer una clase, no cómo. Una clase usa la palabra clave implements para adoptar una interfaz y debe aportar un cuerpo para cada método abstracto que la interfaz declara. Las interfaces permiten que clases sin relación entre sí se usen de forma intercambiable a través de un tipo compartido.
¿Cuál es la diferencia entre una interfaz y una clase abstracta en Java?
Una clase puede implementar muchas interfaces, pero solo puede extender una clase (abstracta). Las interfaces tradicionalmente no guardan estado de instancia y solo declaran comportamiento, mientras que una clase abstracta puede tener campos, constructores y lógica parcialmente implementada. Usa una interfaz para definir una capacidad que varias clases sin relación pueden compartir; usa una clase abstracta para compartir estado y código común entre subclases estrechamente relacionadas.
¿Puede una interfaz de Java tener cuerpos de método?
Sí, desde Java 8. Los métodos de interfaz marcados como default proporcionan un cuerpo que las clases que la implementan heredan (y pueden sobrescribir), y los métodos de interfaz static ofrecen comportamiento de utilidad invocable sobre la propia interfaz. Los métodos de interfaz normales siguen siendo abstractos -solo una firma- y las clases que la implementan deben definirlos.