我正在用Java实现一个控制台菜单类,大致如下:
public class ConsoleMenu {
private Scanner s = new Scanner(System.in);
private ArrayList<String> menuItems = new ArrayList<>();
public void addMenuItem(String description) {
// ... adds item to the menu
}
public void displayMenu() {
// ... displays the menu
}
public int getUserChoice() {
// ... get the user's choice and returns it.
}
}
目前,该类向用户显示主要内容如下:
1. Add item to shopping list
2. Delete item from shopping list
3. Save shopping list
4. Exit
当用户选择时,
getUserChoice
返回选择的编号(1、2、3 或 4)。
但我想要的是,我希望每个菜单项都由 String
的实例表示,该实例将描述保存为字符串和回调方法,而不是拥有 ConsoleMenuItem
列表,然后拥有getUserChoice
调用该回调方法的方法。
所以,我希望
addMenuItem
方法采用回调方法作为参数,以及需要传递给此回调方法的任何数量/类型的参数。
我设法想出的是:
class ConsoleMenuItem {
private String description;
private Consumer<Object[]> function;
private Object[] args;
ConsoleMenuItem(String description, Consumer<Object[]> function, Object... args) {
this.description = description;
this.function = function;
this.args = args;
}
void execute() {
this.function.accept(this.args);
}
}
public class ConsoleMenu {
private Scanner s = new Scanner(System.in);
private ArrayList<ConsoleMenuItem> menuItems = new ArrayList<>();
public void addMenuItem(String description, Consumer<Object[]> function, Object... args) {
menuItems.add(new ConsoleMenuItem(description, function, args));
}
public void displayMenu() {
// display the menu
}
public void getUserChoice() {
//
}
}
这种方法的问题是它只能采用具有以下签名的回调方法:
void someMethod(Object[] args)
。我怎样才能使任何方法都可以作为回调传递?
单独提供函数和参数实际上没有任何意义。
您也可以直接传递
Runnable
。当您实际调用它时,它不需要参数,但是您可以在构造它时绑定您需要的任何参数。
例如,代替:
new ConsoleMenuItem("description", function1, arg1, arg2);
new ConsoleMenuItem("description", function2, arg1, arg2, arg3);
你可以这样做:
new ConsoleMenuItem("description", () -> function1(arg1, arg2));
new ConsoleMenuItem("description", () -> function2(arg1, arg2, arg3));
通过这样做,您还可以从类型检查中受益,因为您不必被迫接受
Object
作为函数的参数。