11

I've watched and read https://caveofprogramming.com/java/whats-new-in-java-8-lambda-expressions.html and I follow the same pattern I did for runner object which works fine.

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

Then, I try to create a simple interface and class to apply what I learned. I just want to replace the anonymous class with a lambda expression. My understanding is a lambda expression is a shorter code for the anonymous class and improve readability.

So, I tried to initiate another instance called eucalyptus1 and try to @Override the grow() method, but my IDE error message said:

grow() in com.smith.Eucalyptus cannot be applied to (lambda expression)

Could anyone point me out what I misunderstand here?

The code is below:

// 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"));
    }
}
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
Smith Lo
  • 305
  • 3
  • 12

3 Answers3

10

The difference there is that you're trying to override the implementation of Eucalyptus which is a class that implement the interface.

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

All you end up doing there is pass a lambda parameter and of course, a method without arguments in its definition wouldn't compile if supplied with one at the time of method call.


Instead, you can compare the way of implementing the lambda as :

//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();

can be represented as a lambda representation:

Plant lambdaRep =  () -> System.out.println("This is running via lambda from Plant Interface");
lambdaRep.grow();
Naman
  • 27,789
  • 26
  • 218
  • 353
10

Problem

The method grow doesn't take any parameters, so you got the compilation error.

Explanation

The lambda () -> System.out.println("This from Lambda expression") itself can represent a Plant (not Eucalyptus*) instance:

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

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

There is a slight misunderstanding here. A lambda isn't supposed to override a method, it's up to provide a method based on a @FunctionalInterface type.


*If you were to define an Eucalyptus object by a lambda, it would be ambiguous and unclear what method the lambda would represent. Therefore, it's prohibited (even for abstract classes with a single abstract method.)

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
7

Your use of lambda expression is incorrect here.

You use lambda expressions to implement an interface. In this case, you would be providing an implementation of Plant using a lambda expression, rather than calling that interface's method with a lambda expression:

Here's a normal use:

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

In other words, because you're having a functional interface, you should be able to avoid creating classes implementing it (anonymous or not).

So you should not need to create the Eucalyptus class at all.

ernest_k
  • 44,416
  • 5
  • 53
  • 99