Interfaces Java explicadas con ejemplos

Interfaces

La interfaz en Java es un poco como la clase, pero con una diferencia significativa: solointerface puede tener firmas de métodos, campos y métodos predeterminados. Desde Java 8, también puede crear métodos predeterminados. En el siguiente bloque puede ver un ejemplo de interfaz:

public interface Vehicle { public String licensePlate = ""; public float maxVel public void start(); public void stop(); default void blowHorn(){ System.out.println("Blowing horn"); } }

La interfaz anterior contiene dos campos, dos métodos y un método predeterminado. Solo, no es de mucha utilidad, pero generalmente se usan junto con las clases. ¿Cómo? Simple, tienes que asegurarte de que algunos lo clasifiquen implements.

public class Car implements Vehicle { public void start() { System.out.println("starting engine..."); } public void stop() { System.out.println("stopping engine..."); } }

Ahora, hay una regla básica : la clase debe implementar todos los métodos en la interfaz. Los métodos deben tener exactamente la misma firma (nombre, parámetros y excepciones) que se describe en la interfaz. Sin embargo, la clase no necesita declarar los campos, solo los métodos.

Instancias de una interfaz

Una vez que crea una clase Java con implementscualquier interfaz, la instancia del objeto puede ser referenciada como una instancia de la interfaz. Este concepto es similar al de la instanciación de herencia.

// following our previous example Vehicle tesla = new Car(); tesla.start(); // starting engine ...

Una interfaz no puede contener métodos constructores. Por lo tanto, no puede crear una instancia de una interfaz en sí. Debe crear una instancia de alguna clase que implemente una interfaz para hacer referencia a ella.

Piense en las interfaces como un formulario de contrato en blanco o una plantilla.

¿Qué puedes hacer con esta función? ¡Polimorfismo! ¡Solo puede usar interfaces para hacer referencia a instancias de objetos!

class Truck implements Vehicle { public void start() { System.out.println("starting truck engine..."); } public void stop() { System.out.println("stopping truck engine..."); } } class Starter { // static method, can be called without instantiating the class public static void startEngine(Vehicle vehicle) { vehicle.start(); } } Vehicle tesla = new Car(); Vehicle tata = new Truck(); Starter.startEngine(tesla); // starting engine ... Starter.startEngine(tata); // starting truck engine ...

Pero, ¿qué hay de múltiples interfaces?

Sí, puede implementar múltiples interfaces en una sola clase. Mientras que en Herencia dentro de las clases estaba restringido a heredar solo una clase, aquí puede extender cualquier número de interfaces. ¡Pero no olvide implementar todos los métodos de todas las interfaces, de lo contrario la compilación fallará!

public interface GPS { public void getCoordinates(); } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } }

Algunas características de las interfaces

  • Puede colocar variables dentro de una interfaz, aunque no será una decisión sensata ya que las clases no están obligadas a tener la misma variable. En resumen, ¡evite colocar variables!
  • Todas las variables y métodos de una interfaz son públicos, incluso si omite la publicpalabra clave.
  • Una interfaz no puede especificar la implementación de un método en particular. Depende de las clases hacerlo. Aunque ha habido una excepción reciente (ver más abajo).
  • Si una clase implementa múltiples interfaces, entonces existe una posibilidad remota de superposición de firmas de métodos. Dado que Java no permite varios métodos con la misma firma exacta, esto puede generar problemas. Consulte esta pregunta para obtener más información.

Métodos predeterminados de la interfaz

Antes de Java 8, no teníamos forma de dirigir una interfaz para que tuviera una implementación de método particular. Esto genera mucha confusión y roturas de código si se cambia repentinamente la definición de una interfaz.

Supongamos que escribió una biblioteca de código abierto, que contiene una interfaz. Digamos que sus clientes, es decir, prácticamente todos los desarrolladores de todo el mundo, lo están utilizando mucho y están contentos. Ahora ha tenido que actualizar la biblioteca agregando una nueva definición de método a la interfaz para admitir una nueva función. Pero eso rompería todas las compilaciones ya que todas las clases que implementan esa interfaz tienen que cambiar ahora. ¡Qué catástrofe!

Afortunadamente, Java 8 ahora nos proporciona defaultmétodos para interfaces. ¡Un defaultmétodo puede contener su propia implementación directamente dentro de la interfaz! Entonces, si una clase no implementa un método predeterminado, el compilador tomará la implementación mencionada dentro de la interfaz. Bonito, ¿no? Por lo tanto, en su biblioteca, puede agregar cualquier cantidad de métodos predeterminados en las interfaces sin temor a romper nada.

public interface GPS { public void getCoordinates(); default public void getRoughCoordinates() { // implementation to return coordinates from rough sources // such as wifi & mobile System.out.println("Fetching rough coordinates..."); } } public interface Radio { public void startRadio(); public void stopRadio(); } public class Smartphone implements GPS,Radio { public void getCoordinates() { // return some coordinates } public void startRadio() { // start Radio } public void stopRadio() { // stop Radio } // no implementation of getRoughCoordinates() } Smartphone motoG = new Smartphone(); motog.getRoughCoordinates(); // Fetching rough coordinates...

Pero, ¿qué sucede si dos interfaces tienen la misma firma de método?

Pregunta impresionante. En ese caso, si no proporciona la implementación en la clase, el compilador deficiente se confundirá y simplemente fallará. También debe proporcionar una implementación de método predeterminada dentro de la Clase. También hay una forma ingeniosa superde llamar a la implementación que desee:

public interface Radio { // public void startRadio(); // public void stopRadio(); default public void next() { System.out.println("Next from Radio"); } } public interface MusicPlayer { // public void start(); // public void pause(); // public void stop(); default public void next() { System.out.println("Next from MusicPlayer"); } } public class Smartphone implements Radio, MusicPlayer { public void next() { // Suppose you want to call MusicPlayer next MusicPlayer.super.next(); } } Smartphone motoG = new Smartphone(); motoG.next(); // Next from MusicPlayer

Métodos estáticos en interfaces

Otra novedad de Java 8 es la capacidad de agregar métodos estáticos a las interfaces. Los métodos estáticos en interfaces son casi idénticos a los métodos estáticos en clases concretas. La única gran diferencia es que los staticmétodos no se heredan en las clases que implementan la interfaz. Esto significa que se hace referencia a la interfaz cuando se llama al método estático, no a la clase que lo implementa.

interface MusicPlayer { public static void commercial(String sponsor) { System.out.println("Now for a message brought to you by " + sponsor); } public void play(); } class Smartphone implements MusicPlayer { public void play() { System.out.println("Playing from smartphone"); } } class Main { public static void main(String[] args) { Smartphone motoG = new Smartphone(); MusicPlayer.commercial("Motorola"); // Called on interface not on implementing class // motoG.commercial("Motorola"); // This would cause a compilation error } }

Heredar una interfaz

También es posible en Java que una interfaz herede otra interfaz, usando, lo adivinó, la extendspalabra clave:

public interface Player { public void start(); public void pause(); public void stop(); } public interface MusicPlayer extends Player { default public void next() { System.out.println("Next from MusicPlayer"); } }

Eso significa que la MusicPlayerinterfaz de implementación de la clase tiene que implementar todos los métodos MusicPlayery también Player:

public class SmartPhone implements MusicPlayer { public void start() { System.out.println("start"); } public void stop() { System.out.println("stop"); } public void pause() { System.out.println("pause"); } }

¡Así que ahora tiene un buen conocimiento de las interfaces Java! Obtenga más información sobre las clases abstractas para ver cómo Java le brinda otra forma de definir contratos.