This site requires JavaScript, please enable it in your browser!
Greenfoot back
Roshan123
Roshan123 wrote ...

2022/2/2

Lamda expression and double colon operator

Roshan123 Roshan123

2022/2/2

#
1) what is the use of.... 2) when to use...... 3) why to use...... 4) How to use..... (plz provide an example) Here “ ...... „ represents “ -> and ::
danpost danpost

2022/2/2

#
Roshan123 wrote...
1) what is the use of.... 2) when to use...... 3) why to use...... 4) How to use..... (plz provide an example) Here “ ...... „ represents “ -> and ::
Lambda expressions are discussed in the java tutorials here. The following two pages also may be helpful.
RcCookie RcCookie

2022/2/2

#
Lambda expressions basically allow you to pass functions as parameters. Look at this example: Say we want to make a button. We may have a class similar to this:
public class Button extends Actor {

    public void act() {
        if(Greenfoot.mouseClicked(this))
            onClick();
    }

    public void onClick() {
        System.out.println("Hello World!");
    }
}
This is nice, but useless. It only ever prints out "Hello World!" when it is clicked, which is funny, but not helpful for creating something else. So, you may make Button and the onClick() abstract and override the class for every button you make:
public abstract class Button extends Actor {
    // ...
    public abstract void onClick();
public class HelloWorldButton extends Button {
    @Override
    public void onClick() {
        System.out.println("Hello World!");
    }
}
public class StopButton extends Button {
    @Override
    public void onClick() {
        Greenfoot.stop();
    }
}
This is better, as you can define what your button actually should do. However, you need a new class for every single Button you make, which is not very handy. Which is why we go a step further and create a new interface with just one method in it. This method should get called when the button gets clicked:
public interface Runnable {
    void run();
}
Now we change the Button class to be non-abstract again and take such a Runnable as input (note that this Runnable interface is predefined in java.lang, so you don't need to create or import it):
public class Button extends Actor {

    private Runnable onClick;

    public Button(Runnable onClick) {
        this.onClick = onClick;
    }

    public void act() {
        if(Greenfoot.mouseClicked(this))
            onClick.run();
    }
}
Now we can create a new Button and pass it a Runnable. We don't have to declare the Runnable implementation explicitly, we can inline it:
Button stopButton = new Button(new Runnable() {
    @Override
    public void run() {
        Greenfoot.stop();
    }
});
Now this is quite a lot of code just for creating a Runnable that calls Greenfoot.stop(). This is where lambda expressions come in handy. They describe the same, but are much shorter. For example, the above example could be written as follows:
Button stopButton = new Button(() -> Greenfoot.stop());
Let's look at the syntax. Before the arrow we list the parameters of the method we override (here: the "run" method from Runnable). If you for example had three parameters, you could write
(a,b,c) ->
Where a would be the first parameter, b the second and c the third. In our case we don't have any parameters, so the brackets are empty. Note that you can omit the brackets if you have exactly one parameter. After the arrow comes the method body. It can be written as usual, starting and ending with curly brackets:
-> {
    // line of code
    // another line of code
}
Similar to the parameters, you can omit these brackets if you have exactly a single line of code, which you will find quite often. Thus why there are no curly brackets around the "Greenfoot.stop()" in the example above. Finally, to address the double colon syntax, it is an even shorter from to write a lambda expression. It can only be used if the following criteria are true:
  • The lambda expression has exactly a single line of code
  • The expression has exactly one method call, as the final part of the line of code
  • The parameters and the return type of the method you want to call are identical to the types and order from the interface the lambda expression overrides
All these criteria are fullfilled by our example button: - One line of code: "Greenfoot.stop()" - Exactly one method call as last part: "stop()" on the Greenfoot class - Same parameters and return type: Both "run()" from Runnable and "stop()" from Greenfoot take no parameters and are void methods. In this case, we can write our Button as follows:
Button stopButton = new Button(Greenfoot::stop);
Before the double colons you say the object or class of the method, and after the colon the name of the method.
RcCookie RcCookie

2022/2/2

#
Danpost's link is also worth checking out, they go into a lot more detail, for example how to return values from a lambda statement.
Roshan123 Roshan123

2022/2/3

#
Thanks a lot to both of you If I am not wrong, their not nothing so special about lambda. It only makes a program readable & saves time. I other words, we don't have to make a class which will be implementing the abstract class and then create new constructor of it to call the abstract method. @RcCookie can it be also written as
Button stopButton = () -> Greenfoot.stop();
?
RcCookie RcCookie

2022/2/3

#
Roshan123 wrote...
Thanks a lot to both of you @RcCookie can it be also written as
Button stopButton = () -> Greenfoot.stop();
?
No, because Button is not the interface with one method. But you could write
Runnable stopAction = () -> Greenfoot.stop();
// or
Runnable stopAction = Greenfoot::stop;
You need to login to post a reply.