Question:
How can this code be executed and compiled if, with action.perform, the perform method is not even defined. And plus a command like editor at the moment m.record(editor::save);
, and the macro list itself is intended for objects of type action? How can this be?
public class Macro {
List<Actiona> macro;
Macro(){
macro = new ArrayList<>();
}
public void record(Actiona action){
macro.add(action);
}
public void run(){
macro.forEach(Actiona::perform);
}
public static void main(String[] args) {
MockEditor editor = new MockEditor();
Macro m = new Macro();
m.record(editor::save);
m.record(editor::close);
m.run();
}
}
public class MockEditor implements Editor {
@Override
public void save() {
System.out.println("Save");
}
@Override
public void close() {
System.out.println("close");
}
}
public interface Actiona {
public void perform();
}
public interface Editor {
public void save();
public void close();
}
Answer:
This magic is easy to understand if you go to an IDE (say IDEA) and ask to replace the lambda with an anonymous class:
public static void main(String[] args) {
MockEditor editor = new MockEditor();
Macro m = new Macro();
m.record(new Actiona() { // вместо m.record(editor::save);
@Override
public void perform() {
editor.save();
}
});
m.record(new Actiona() { // вместо m.record(editor::close);
@Override
public void perform() {
editor.close();
}
});
m.run(); // Вызываем метод с двумя объектами Actiona
And suddenly everything becomes simple and clear, we implement the perform method by calling the editor.save()
and editor.close()
methods internally, so the behavior is quite correct.
A very good skill, as soon as you get confused in lambda functions, replace them mentally (or using the IDE) with anonymous classes and life becomes easier.