Una interfaz en el lenguaje de programación Java es un tipo abstracto que se utiliza para declarar un comportamiento que las clases deben implementar. Son similares a los protocolos . Las interfaces se declaran utilizando la interface
palabra clave , y solo pueden contener la firma del método y las declaraciones de constantes (declaraciones de variables que se declaran como static
y final
). Todos los métodos de una interfaz no contienen implementación (cuerpos de método) a partir de todas las versiones anteriores a Java 8. A partir de Java 8, default
[1] : 99 y static
[1] : 7 los métodos pueden tener implementación en la interface
definición. [2] Luego, en Java 9, se agregaron los métodos private
y private static
. En la actualidad, una interfaz Java puede tener hasta seis tipos diferentes.
Las interfaces no se pueden instanciar , sino que se implementan. Una clase que implementa una interfaz debe implementar todos los métodos no predeterminados descritos en la interfaz, o ser una clase abstracta . Las referencias a objetos en Java se pueden especificar para que sean de un tipo de interfaz; en cada caso, deben ser null o estar vinculadas a un objeto que implemente la interfaz.
Una ventaja de usar interfaces es que simulan la herencia múltiple . Todas las clases en Java deben tener exactamente una clase base , con la única excepción de java.lang.Object
la clase raíz del sistema de tipos de Java ; no se permite la herencia múltiple de clases. Sin embargo, una interfaz puede heredar múltiples interfaces y una clase puede implementar múltiples interfaces.
Las interfaces se utilizan para codificar similitudes que comparten las clases de varios tipos, pero que no necesariamente constituyen una relación de clase. Por ejemplo, un humano y un loro pueden silbar ; sin embargo, no tendría sentido representar Human
s y Parrot
s como subclases de una Whistler
clase. Lo más probable es que sean subclases de una Animal
clase (probablemente con clases intermedias), pero ambas implementarían la Whistler
interfaz.
Otro uso de las interfaces es poder usar un objeto sin saber su tipo de clase, sino solo que implementa una determinada interfaz. Por ejemplo, si a uno le molesta un silbido, es posible que no sepa si es un humano o un loro, porque todo lo que se puede determinar es que un silbador está silbando. La llamada whistler.whistle()
llamará al método implementado whistle
de object whistler
sin importar qué clase tenga, siempre que implemente Whistler
. En un ejemplo más práctico, un algoritmo de ordenamiento puede esperar un objeto de tipo Comparable
. Por lo tanto, sin conocer el tipo específico, sabe que los objetos de ese tipo se pueden ordenar de alguna manera.
Por ejemplo:
interfaz Bounceable { double pi = 3.1415 ; void setBounce (); // Tenga en cuenta el punto y coma // Los métodos de interfaz son públicos, abstractos y nunca finales. // Piense en ellos solo como prototipos; no se permiten implementaciones. }
Una interfaz:
Las interfaces se definen con la siguiente sintaxis (compárese con la definición de clase de Java ):
[ visibilidad ] interfaz InterfaceName [extiende otras interfaces ] { declaraciones de constantes declaraciones de métodos abstractos declaraciones de métodos estáticos}
Ejemplo: interfaz pública Interface1 extiende Interface2;
El cuerpo de la interfaz contiene métodos abstractos , pero como todos los métodos de una interfaz son, por definición, abstractos, abstract
no se requiere la palabra clave. Como la interfaz especifica un conjunto de comportamientos expuestos, todos los métodos son implícitamente abstractos public
.
De esta manera, se puede crear una interfaz sencilla.
Interfaz pública Depredador { booleano chasePrey ( Prey p ); void eatPrey ( Prey p ); }
Las declaraciones de tipo de miembro en una interfaz son implícitamente estáticas, finales y públicas, pero por lo demás pueden ser cualquier tipo de clase o interfaz. [3]
La sintaxis para implementar una interfaz utiliza esta fórmula:
... implementa InterfaceName [, otra interfaz , otra , ...] ...
Las clases pueden implementar una interfaz. Por ejemplo:
La clase pública Lion implementa Predator { @Override public boolean chasePrey ( Prey p ) { // Programación para perseguir a la presa p (específicamente para un león) } @Override public void eatPrey ( Prey p ) { // Programación para comer la presa p (específicamente para un león) } }
Si una clase implementa una interfaz y no implementa todos sus métodos, debe marcarse como abstract
. Si una clase es abstracta, se espera que una de sus subclases implemente sus métodos no implementados, aunque si alguna de las subclases de la clase abstracta no implementa todos los métodos de la interfaz, la subclase en sí misma debe marcarse nuevamente como abstract
.
Las clases pueden implementar múltiples interfaces:
La clase pública Frog implementa Predator , Prey { ... }
Las interfaces pueden compartir métodos de clase comunes:
clase Animal implementa LikesFood , LikesWater { boolean likes () { return true ; } }
Sin embargo, una clase determinada no puede implementar la misma interfaz o una interfaz similar varias veces:
clase Animal implementa Shares < Boolean > , Shares < Integer > ... // Error: interfaz repetida
Las interfaces se utilizan comúnmente en el lenguaje Java para las devoluciones de llamadas , [4] ya que Java no permite la herencia múltiple de clases, ni permite el paso de métodos (procedimientos) como argumentos. Por lo tanto, para pasar un método como parámetro a un método de destino, la práctica actual es definir y pasar una referencia a una interfaz como un medio para proporcionar la firma y la dirección del método de parámetro al método de destino en lugar de definir múltiples variantes del método de destino para dar cabida a cada posible clase de llamada.
Las interfaces pueden extender varias otras interfaces, utilizando la misma fórmula que se describe a continuación. Por ejemplo,
Interfaz pública VenomousPredator extiende Predator , Venomous { // Cuerpo de la interfaz }
es legal y define una subinterfaz. Permite herencia múltiple, a diferencia de las clases. Predator
y Venomous
posiblemente puede definir o heredar métodos con la misma firma, por ejemplo kill(Prey p)
. Cuando una clase se implementa, VenomousPredator
implementará ambos métodos simultáneamente.
Algunas interfaces Java comunes son:
Comparable
tiene el método compareTo
, que se utiliza para describir dos objetos como iguales o para indicar que uno es mayor que el otro. Los genéricos permiten que las clases implementadoras especifiquen qué instancias de clase se pueden comparar con ellas.Serializable
es una interfaz de marcador sin métodos ni campos; tiene un cuerpo vacío. Se utiliza para indicar que una clase se puede serializar . Su Javadoc describe cómo debería funcionar, aunque no se aplica nada programáticamente.