I'm trying to transform this code to work without using lambdas so that I can better understand it, but I am having no luck at all. How can I write it with ActionEvent
s similar to buttons?
enemyBoard = new Board(true, event -> {
if (!running)
return;
Cell cell = (Cell) event.getSource();
if (cell.wasShot)
return;
enemyTurn = !cell.shoot();
if (enemyBoard.ships == 0) {
System.out.println("YOU WIN");
System.exit(0);
}
if (enemyTurn)
enemyMove();
});
Here is the Board
constructor:
public Board(boolean enemy, EventHandler<? super MouseEvent> handler) {
this.enemy = enemy;
for (int y = 0; y < 10; y++) {
HBox row = new HBox();
for (int x = 0; x < 10; x++) {
Cell c = new Cell(x, y, this);
c.setOnMouseClicked(handler);
row.getChildren().add(c);
}
rows.getChildren().add(row);
}
getChildren().add(rows);
}
The code belongs to a battleship game, and here is the link to the game code: https://github.com/AlmasB/Battleship/tree/master/src/com/almasb/battleship.
enemyBoard = new Board(true, event -> { ... });
A lambda is a shorthand way of implementing a functional interface, which is an interface
with a single (non-default
) method. The equivalent code without a lambda is:
enemyBoard = new Board(true, new EventHandler<MouseEvent>() {
public void handle(MouseEvent event) {
...
}
});
That's it. It's just syntactic sugar† for instantiating an anonymous EventHandler
and implementing its single handle()
method.
I've elided the method body because it's the same in both.
If that still looks weird, writing new ClassOrInterface() { ... }
is itself also a form of syntactic sugar. We could apply another round of de-sugaring and write out the anonymous class explicitly:
class EventHandler$1 implements EventHandler<MouseEvent> {
public void handle(MouseEvent event) {
...
}
}
enemyBoard = new Board(true, new EventHandler$1());
Note that EventHandler$1
is an auto-generated class name that is guaranteed not to clash with any other real classes. The compiler uses a $
character, which isn't legal in end user code, to name the class such that it couldn't possible conflict. If you've ever seen class names with dollar signs in your stack traces, this is where they come from: anonymous classes.
† As @user points out, it's actually more complicated under the covers. Lambdas don't always de-sugar to an anonymous class. Often the compiler can do something a little more efficient. But conceptually, thinking of them as anonymous classes is a good way to mentally translate them.