lunes, 25 de junio de 2018

Java 8: Las Interfaces nuevos métodos y tipos

Vamos a intentar hacer una serie de post sobre Java 8 que se centren algo más en cada una de las que según para mí son las caracteristicas más interesantes. En este post nos centraremos en las interfaces y sus nuevos métodos estáticos y por defecto además de las nuevas interfaces funcionales.
  • Métodos estáticos
Podemos crear interfaces con métodos estáticos como lo hemos hecho siempre con las clases. Y tantos como queramos. Estos métodos no pueden sobrescribirse, podrás crear otro con el mismo nombre en la clase que la extienda, pero la lógica no será la misma. 

public interface Aleatorio {
    static int dameUnoDe50() {
 return new Random().nextInt(50);
    }
    static int dameUnoDe20() {
 return new Random().nextInt(20);
    }
}
//....
public static void main(final String[] args) {
    System.out.println(Aleatorio.dameUnoDe50());
}
  • Métodos por defecto
Estos proveerán de una implementación por defecto a todas las clases que implementen la interfaz. Pero a la vez podrá ser sobrescrito por la clase y en este caso no podrá ser invocador por la interfaz como se realiza en el caso anterior.

public interface Aleatorio {
    static int dameUnoDe50() {
 return new Random().nextInt(50);
    }
    static int dameUnoDe20() {
 return new Random().nextInt(20);
    }
    default int dameUnoDe10() {
 return new Random().nextInt(10);
    }
}
//...
public class EnteroAleatorio implements Aleatorio {
    @Override
    public int dameUnoDe10() {
 return 10;
    }
    public static void main(final String[] args) {
 Aleatorio objAle = new EnteroAleatorio();
 System.out.println(objAle.dameUnoDe10());
    }
}
  • Interfaces funcionales
Esta nueva caracteristica de Java 8 gana relevancia y utilidad al usarse conjuntamente al lenguaje lambda. Y se dira que es una interfaz funcional toda interfaz que independientemente del número de métodos por defecto que tenga, tenga a su vez un único método abstracto. 

Y esto es porque se nos permitirá a través del lambda invocar a una interfaz con su método abstracto asociado e implementarlo y ejecutarlo en el momento de la invocación. 

public interface Aleatorio {
    int dameLoQueQuieras(Integer number);
    static int dameUnoDe50() {
 return new Random().nextInt(50);
    }
    static int dameUnoDe20() {
 return new Random().nextInt(20);
    }
    default int dameUnoDe10() {
 return new Random().nextInt(10);
    }
}
//...
public class EnteroAleatorio implements Aleatorio {
    @Override
    public int dameUnoDe10() {
 return 10;
    }
    @Override
    public int dameLoQueQuieras(final Integer number) {
 return 0;
    }
    public static void main(final String[] args) {
 Aleatorio intAle = (numero) -> new Random().nextInt(numero);
 Aleatorio objAle = new EnteroAleatorio();
 System.out.println(intAle.dameLoQueQuieras(200));
 System.out.println(objAle.dameLoQueQuieras(200));
    }
}

Si incluimos más de un  método abstracto tendremos un error en tiempo de compilación pero al intentar usarla (en el método static void main). Para evitar esto y que nos salte en la propia interfaz podemos usar la anotación @FunctionalInterface.




No hay comentarios:

Publicar un comentario