He visto y leído https://caveofprogramming.com /java/whats-new-in-java-8-lambda-expressions.html y sigo el mismo patrón que hice para el objeto corredor que funciona bien.

Runner runner = new Runner();
runner.run(() -> System.out.println("Print from Lambda expression"));

Luego, trato de crear una interfaz simple y una clase para aplicar lo que aprendí. Solo quiero reemplazar la clase anónima con una expresión lambda. Entiendo que una expresión lambda es un código más corto para la clase anónima y mejora la legibilidad.

Entonces, intenté iniciar otra instancia llamada eucalyptus1 e intenté @Override el método grow(), pero mi mensaje de error IDE decía:

grow() en com.smith.Eucalyptus no se puede aplicar a (lambda expression)

¿Alguien podría señalarme lo que no entiendo aquí?

El código es el siguiente:

// a simple interface
interface Plant {
    public void grow();
}

// apply interface to class
class Eucalyptus implements Plant {
    @Override
    public void grow() {
        System.out.println("This is from Eucalyptus");
    }
}

public class Main {
    public static void main(String[] args) {

        // Create an instance of Eucalyptus
        Eucalyptus eucalyptus = new Eucalyptus();
        eucalyptus.grow();

        // Anonymous class Myrtle from Plant interface
        Plant myrtle = new Plant() {
            @Override
            public void grow() {
                System.out.println("This was running from anonymous class from Plant Interface");
            }
        };

        myrtle.grow();

        // Try to create a lambda expression from Plant interface
        // and override grow() method
        // by print ("This was running from Lambda expression")

        // this won't work. why?
        Eucalyptus eucalyptus1 = new Eucalyptus();
        eucalyptus1.grow(() -> System.out.println("This from Lambda expression"));
    }
}
11
Smith Lo 10 sep. 2018 a las 13:11

3 respuestas

La mejor respuesta

La diferencia es que está intentando anular la implementación de Eucalyptus, que es una clase que implementa la interfaz.

Eucalyptus eucalyptus1 = new Eucalyptus();
eucalyptus1.grow(() -> System.out.println("This from Lambda expression")); 
^__  // you cannot override a method using an instance of a class which is just an implementation of the interface

Todo lo que terminas haciendo allí es pasar un parámetro lambda y, por supuesto, un método sin argumentos en su definición no se compilaría si se proporcionara uno en el momento de la llamada al método.


En cambio, puede comparar la forma de implementar el lambda como:

//Anonymous class Myrtle from Plant interface
Plant myrtle = new Plant() {
          @Override
          public void grow() {
               System.out.println("This was running from anonymous class from Plant Interface");
          }
};
myrtle.grow();

Se puede representar como una representación lambda:

Plant lambdaRep =  () -> System.out.println("This is running via lambda from Plant Interface");
lambdaRep.grow();
10
Naman 10 sep. 2018 a las 10:23

Su uso de la expresión lambda es incorrecto aquí.

Utiliza expresiones lambda para implementar una interfaz. En este caso, proporcionaría una implementación de Plant utilizando una expresión lambda, en lugar de llamar al método de esa interfaz con una expresión lambda:

Aquí hay un uso normal:

Plant eucalyptus1 = () -> System.out.println("This from Lambda expression");
eucalyptus1.grow(); // Prints "This from Lambda expression"

En otras palabras, debido a que tiene una interfaz funcional, debería ser capaz de evitar crear clases que la implementen (anónima o no).

Por lo tanto, no debería necesitar crear la clase Eucalyptus en absoluto.

7
ernest_k 10 sep. 2018 a las 10:18

Problema

El método grow no toma ningún parámetro, por lo que obtuvo el error de compilación.

Explicación

La lambda () -> System.out.println("This from Lambda expression") en sí misma puede representar una instancia Plant (no Eucalyptus *):

Plant plant = () -> System.out.println("This from Lambda expression");

Intente crear una expresión lambda desde la interfaz Plant y anular el método grow() imprimiendo "This was running from Lambda expression".

Hay un ligero malentendido aquí. No se supone que una lambda anule un método , depende de proporcionar un método basado en un tipo @FunctionalInterface.


* Si tuviera que definir un objeto Eucalyptus por una lambda, sería ambiguo y poco claro qué método representaría la lambda. Por lo tanto, está prohibido (incluso para clases abstractas con un único método abstracto)

10
Andrew Tobilko 10 sep. 2018 a las 10:39