interfaces - java 8 lambda explicacion
¿Por qué necesito una interfaz funcional para trabajar con lambdas? (5)
Creo que esta pregunta ya está en algún lugar, pero no pude encontrarla.
No entiendo, por qué es necesario tener una interfaz funcional para trabajar con las lambdas. Considere el siguiente ejemplo:
public class Test {
public static void main(String...args) {
TestInterface i = () -> System.out.println("Hans");
// i = (String a) -> System.out.println(a);
i.hans();
// i.hans("Hello");
}
}
public interface TestInterface {
public void hans();
// public void hans(String a);
}
Esto funciona sin problemas, pero si elimina el comentario de las líneas comentadas, no lo hace. ¿Por qué? A mi entender, el compilador debería poder distinguir los dos métodos, ya que tienen diferentes parámetros de entrada. ¿Por qué necesito una interfaz funcional y explotar mi código?
EDITAR: Los duplicados vinculados no respondieron a mi pregunta porque estoy preguntando acerca de diferentes métodos-parámetros. ¡Pero recibí algunas respuestas realmente útiles aquí, gracias a todos los que ayudaron! :)
EDIT2: Lo siento, obviamente no soy un hablante nativo, pero para precisarme:
public interface TestInterface {
public void hans(); //has no input parameters</br>
public void hans(String a); //has 1 input parameter, type String</br>
public void hans(String a, int b); //has 2 input parameters, 1. type = String, 2. type = int</br>
public void hans(int a, int b); //has also 2 input parameters, but not the same and a different order than `hans(String a, int a);`, so you could distinguish both
}
public class Test {
public static void main(String...args) {
TestInterface i = () -> System.out.println("Hans");
i = (String a) -> System.out.println(a);
i = (String a, int b) -> System.out.println(a + b);
i = (int a, int b) -> System.out.println(a);
i.hans(2, 3); //Which method would be called? Of course the one that would take 2 integer arguments. :)
}
}
Todo lo que pregunto es sobre los argumentos. El nombre del método no importa, pero cada método toma un orden único de argumentos diferentes y debido a eso, Oracle podría haber implementado esta función en lugar de hacer posible un solo método por "Lambda-Interface".
Cuando escribes :
TestInterface i = () -> System.out.println("Hans");
Usted da una implementación al método void hans()
de TestInterface
.
Si pudiera asignar una expresión lambda a una interfaz que tenga más de un método abstracto (es decir, una interfaz no funcional), la expresión lambda solo podría implementar uno de los métodos, dejando los otros métodos sin implementar.
No puede resolverlo asignando dos expresiones lambda que tengan firmas diferentes a la misma variable (al igual que no puede asignar referencias de dos objetos a una sola variable y esperar que esa variable se refiera a ambos objetos a la vez).
La interfaz funcional solo puede contener exactamente un método abstracto según las especificaciones de java .
Seguramente la expresión lambda puede usarse una sola vez como lo hace el código comentado, pero cuando se trata de pasar la expresión lambda como parámetro para imitar la devolución de llamada de la función, la interfaz funcional es imprescindible porque en ese caso el tipo de datos variables es la interfaz funcional.
Por ejemplo, Runnable
es una interfaz funcional integrada:
public interface Runnable() {
public void run();
}
El uso se puede demostrar de la siguiente manera:
public class LambdaTest {
// data type of parameter ''task'' is functional interface ''Runnable''
static void doSeveralTimes(Runnable task, int repeat) {
for (int i = 0; i < repeat; i++) {
task.run();
}
}
public static void main(String[] args) {
// one-time lambda
doSeveralTimes(() -> {
System.out.println("one-time lambda");
}, 3);
// lambda as variable
Runnable test;
test = () -> {
System.out.println("lambda as variable");
};
doSeveralTimes(test, 3);
}
}
y el resultado es:
one-time lambda
one-time lambda
one-time lambda
lambda as variable
lambda as variable
lambda as variable
La razón más importante por la que deben contener un solo método, es que la confusión es fácilmente posible de lo contrario. Si se permitieron múltiples métodos en la interfaz, ¿qué método debería elegir una lambda si las listas de argumentos son las mismas?
interface TestInterface {
void first();
void second(); // this is only distinguished from first() by method name
String third(); // maybe you could say in this instance "well the return type is different"
Object fourth(); // but a String is an Object, too !
}
void test() {
// which method are you implementing, first or second ?
TestInterface a = () -> System.out.println("Ido mein ado mein");
// which method are you implementing, third or fourth ?
TestInterface b = () -> "Ido mein ado mein";
}
No es necesario crear una interfaz funcional para crear la función lambda. La interfaz le permite crear instancias para futuras invocaciones de funciones.
En tu caso podrías usar la interfaz ya existente Ejecutable
Runnable r = () -> System.out.println("Hans");
y luego llamar
r.run();
Puedes pensar en lambda ->
como una mano corta para:
Runnable r = new Runnable() {
void run() {
System.out.println("Hans");`
}
}
Con lambda no necesita la clase anónima, que se crea bajo el capó en el ejemplo anterior.
Pero esto tiene alguna limitación, para averiguar qué método debe llamarse interfaz utilizada con lambdas debe ser SAM (Método abstracto único). Entonces tenemos un solo método.
Para una explicación más detallada lea:
Introducción a las interfaces funcionales: un concepto recreado en Java 8
Parece que estás buscando clases anónimas . El siguiente código funciona:
public class Test {
public static void main(String...args) {
TestInterface i = new TestInterface() {
public void hans() {
System.out.println("Hans");
}
public void hans(String a) {
System.out.println(a);
}
};
i.hans();
i.hans("Hello");
}
}
public interface TestInterface {
public void hans();
public void hans(String a);
}
Las expresiones Lambda son (en su mayoría) una forma más corta de escribir clases anónimas con un solo método. (Del mismo modo, las clases anónimas son abreviadas para las clases internas que solo usas en un lugar)