English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Tutoriales básicos de Java

Control de flujo de Java

Java array

Java orientado a objetos (I)

Java orientado a objetos (II)

Java orientado a objetos (III)

Manejo de excepciones en Java

Java Lista (List)

Java Queue (cola)

Conjuntos de Map de Java

Conjuntos de Java

Entrada y salida de Java (I)/)

Reader de Java/Writer

Otras temáticas de Java

Interfaz (Interface) en Java

En este tutorial, aprenderemos sobre las interfaces de Java. A través de ejemplos, aprenderemos cómo implementar interfaces y cuándo utilizarlas.

En Java, un interfaz define un conjunto de especificaciones que otros clases deben implementar. Por ejemplo,

interface Polygon {
   public void getArea();
}

Aquí Polygon es un interfaz. Utilizamos la palabra clave interface para declarar un interfaz.

El método getArea() es una especificación definida en el interfaz Polygon. Todos los clases que utilicen este interfaz deben implementar el método getArea().

Un interfaz puede contener métodos abstractos y constantes. Por ejemplo,

interface Polygon {
   public static final String color = "blue";
   
   public void getArea();
}

En el ejemplo anterior, creamos un interfaz Polygon. Este incluye una variable constante color y un método abstracto getArea().

Es importante tener en cuenta que todos los métodos dentro del interfaz son implícitamente publicos, y todos los campos son implícitamente public static final. Por lo tanto, no es necesario especificar el modificador de acceso dentro del interfaz. Por ejemplo, podemos escribir el código anterior de la siguiente manera

interface Polygon {
   String color = "blue";
   
    void getArea();
}

Interface y palabra clave implements

Al igual que las clases abstractas, no podemos crear objetos de interfaz. Sin embargo, podemos implementar interfaces en otras clases. En Java, usamos la palabra clave implements para implementar interfaces. Por ejemplo,

interface Polygon {
    void getArea(int longitud, int ancho);
}
class Rectangle implements Polygon {
    public void getArea(int longitud, int ancho) {
        System.out.println("El área del rectángulo es " + (longitud * ancho));
    }
}
class Main {
    public static void main(String[] args) {
        Rectangle r1 = new Rectangle();
        r1.getArea(5, 6);
    }
}

Resultado de salida

El área del rectángulo es 30

En el programa anterior, creamos una interfaz Polygon. La interfaz Polygon tiene un método abstracto getArea().

 Esto significa que cualquier clase que implemente Polygon debe proporcionar la implementación del método getArea().

Nota, la clase Rectangle (que implementa la interfaz Polygon) tiene el método con implementación getArea().

¿Por qué usar interfaces?

Ahora que sabemos qué es una interfaz, veamos por qué se utiliza una interfaz en Java.

  • Las interfaces proporcionan las especificaciones que la clase (que las implementa) debe seguir.

  • En el ejemplo anterior, hemos utilizado getArea() como la especificación en la interfaz Polygon. Esto es como establecer una regla, es decir, deberíamos poder obtener el área de cada polígono. Por lo tanto, cualquier clase que implemente la interfaz Polygon debe proporcionar la implementación del método getArea().

  • Al igual que las clases abstractas, las interfaces pueden ayudarnos a implementar la abstracción en Java. Aquí, sabemos que getArea() calcula el área del polígono, pero para diferentes polígonos, la forma de calcular el área es diferente. Por lo tanto, las implementaciones de getArea() son independientes.

  • Las interfaces también se utilizan para lograr la herencia múltiple en Java. Si una subclase se deriva de dos o más clases, es herencia múltiple.

    En Java, no se puede lograr la herencia múltiple a través de la herencia de clases. Sin embargo, una clase puede implementar múltiples interfaces. Esto nos permite obtener la funcionalidad de herencia múltiple en Java. Por ejemplo,

    interface Line {
       ...
    }
    interface Polygon {
       ...
    }
    class Rectangle implements Line, Polygon{
       ...
    }

    Aquí, Rectangle debe proporcionar la implementación de todos los métodos de Line y Polygon.

Métodos privados y estáticos en la interfaz

Java 8en la que la interfaz ahora puede contener métodos estáticos.

Al igual que las clases, podemos usar su referencia para acceder a los métodos estáticos de la interfaz. Por ejemplo,

Polygon.staticMethod();

Además, en Java, la interfaz 9El soporte para métodos privados está disponible en la versión de lanzamiento. Ahora, puede usarmétodo privadoyMétodo estático privado

Dado que no se puede instanciar una interfaz, se utiliza el método privado como método auxiliar para proporcionar apoyo a otros métodos en la interfaz.

métodos predeterminados en la interfaz

Java 8en el que se introdujo un método con implementación (método predeterminado) en la interfaz. Y antes de eso, todos los métodos eran métodos abstractos en Java.

Para declarar métodos predeterminados en la interfaz, usamos la palabra clave default. Por ejemplo,

public default void getSides() {
   //El cuerpo del método getSides()
}

¿Por qué usar métodos predeterminados?

Vamos a entender por qué Java introdujo métodos predeterminados con un escenario.

Supongamos que necesitamos agregar un nuevo método en la interfaz.

Podemos agregar fácilmente este método en la interfaz sin ejecutar. Pero, esto no es el final de la historia. Todas las clases que implementan esta interfaz deben proporcionar la implementación de este método.

Si muchos clases están implementando este interfaz, necesitamos rastrear todas estas clases y cambiarlas. Esto no solo es tedioso, sino que también es susceptible a errores.

Para resolver este problema, Java introdujo métodos predeterminados. Los métodos predeterminados heredan como métodos normales.

Vamos a usar un ejemplo para entender mejor el método predeterminado.

Ejemplo2:método predeterminado

interface Polygon {
   void getArea();
   default void getSides() {
      System.out.println("Puedo obtener los lados del polígono.");
   }
}
class Rectangle implements Polygon {
   public void getArea() {
      int length = 6;
      int breadth = 5;
      int area = length * breadth;
      System.out.println("El área del rectángulo es "+area);
   }
   public void getSides() {
      System.out.println("Tengo cuatro lados.");
   }
}
class Square implements Polygon {
   public void getArea() {
      int length = 5;
      int area = length * length;
      System.out.println("El área del cuadrado es "+area);
   }
}
class Main {
   public static void main(String[] args) {
      Rectangle r1 = new Rectangle();
      r1.getArea();
      r1.getSides();
      Square s1 = new Square();
      s1.getArea();
   }
}

Resultado de salida

El área del rectángulo es 30
Tengo cuatro lados.
El área del cuadrado es 25

En el ejemplo anterior, creamos una interfaz Polygon. Polygon tiene un método predeterminado getSides() y un método abstracto getArea().

Luego, la clase Rectangle implementa Polygon, Rectangle proporciona la implementación del método abstracto getArea() y sobrescribe el método predeterminado getSides().

Creamos otra clase Square, que también implementa Polygon. Aquí, Square proporciona únicamente la implementación del método abstracto getArea().

Ejemplo de aplicación real de la interfaz

Veamos un ejemplo más práctico de interfaz de Java.

//Uso de la función sqrt
import java.lang.Math;
interface Polygon {
   void getArea();
  
     //Calcular el perímetro del polígono
   default void getPerimeter(int... sides) {
      int perimeter = 0;
      for (int side: sides) {
         perimeter += side;
      }
   System.out.println("Perímetro: " + perimeter);
   }
}
class Triangle implements Polygon {
   private int a, b, c;
   private double s, area;
    //Inicializar los lados del triángulo
   Triangle(int a, int b, int c) {
      this.a = a;
      this.b = b;
      this.c = c;
      s = 0;
   }
    //Calcular el área del triángulo
   public void getArea() {
      s = (double) (a + b + c)/2;
      area = Math.sqrt(s*(s-a)*(s-b)*(s-c));
      System.out.println("Área: " + area);
   }
}
class Main {
   public static void main(String[] args) {
      Triangle t1 = new Triangle(2, 3, 4);
      //Llamar al método de la clase Triangle
      t1.getArea();
      //Llamar al método de la clase Polygon
      t1.getPerimeter(2, 3, 4);
   }
}

Resultado de salida

Área: 2.9047375096555625
Perímetro: 9

En el programa anterior, creamos una interfaz Polygon. Incluye el método predeterminado getParameter() y el método abstracto getArea().

Podemos calcular el perímetro de todos los polígonos de la misma manera, por lo que implementamos el cuerpo de getPerimeter() en Polygon. Ahora, todos los polígonos que implementan Polygon pueden usar getPerimeter() para calcular el perímetro.

Pero, la forma de calcular el área es diferente para diferentes polígonos, porque las reglas para calcular el área son diferentes para diferentes polígonos.

Por lo tanto, no se ha implementado en Polygon y se incluye getArea(). Y cualquier clase que implemente el interfaz Polygon debe proporcionar la implementación de getArea().

Interfaz y la palabra clave extends

Al igual que las clases, los interfaces pueden heredar de otros interfaces, la palabra clave extends se utiliza para heredar interfaces. Por ejemplo,

interface Line {
   //Miembros del interfaz Line
}
interface Polygon extends Line {
   //Miembros del interfaz Polygon y Line
}

En el ejemplo anterior, el interfaz Polygon extiende el interfaz Line. Ahora, si una clase implementa Polygon, debe proporcionar la implementación de todas las clases abstractas de Line y Polygon.

Atención, un interfaz puede heredar múltiples interfaces, al igual que una clase que implementa múltiples interfaces. Por ejemplo,

interface A {
   ...
}
interface B {
   ... 
}
Interface C extends A, B {
   ...
}