我正在尝试建模一个菜单系统,该系统可以具有包含子菜单的菜单。我想要一个通用的 interface
用于通过其父菜单从菜单和子菜单中检索选项,但我在设计它时遇到了麻烦,同时保持它的类型安全、灵活且没有编译时“不兼容类型”错误。我试图通过使用 Java 泛型来指定 Menu interface
来实现我的目标。用于简单的菜单和 ParentMenu interface
对于使用泛型类型参数作为方法参数和返回类型的父菜单。
我有第三个Enumerable interface
用于表示特定菜单上可用的选项。 implement
的类(class)Enumerable interface
都是enum classes
枚举菜单上的选项。父菜单可以包含许多子菜单,我想要一种通用的单一方法,允许父菜单类的客户端获取其任何一个子菜单的选项。
父菜单具体class
有一个方法,其签名指定返回值 List<Enumerable>
。我希望能够返回 List<MenuOption>
哪里MenuOption
implements
Enumerable interface
。但是,我收到一个错误,指出 List<MenuOption>
我想返回与List<Enumerable>
不兼容。
基本Menu interface
:
package example;
import java.util.List;
public interface Menu<T> {
public List<T> getOptions();
}
ParentMenu interface
:
package example;
import java.util.List;
public interface ParentMenu<T,U> {
public List<T> getSubMenuOptions(U subMenu);
}
`可枚举接口(interface):
package example;
public interface Enumerable {
public String getName();
}
这是 Menu interface
的实现:
package example;
import java.util.*;
public class SimpleMenu implements Menu<MenuOption> {
private final Map<MenuOption, String> menuLinks;
public SimpleMenu() {
menuLinks = new HashMap<>();
for(MenuOption option : MenuOption.values()) {
//Totally arbitrary mapping to avoid adding extra classes and Selenium stuff that is not actually part of
//the question I'm asking.
menuLinks.put(option, option.getName());
}
}
public final List<MenuOption> getOptions() {
Set keys = menuLinks.keySet();
List<MenuOption> options = new ArrayList<MenuOption>(keys);
return options;
}
}
这是 enum class
枚举 SimpleMenu
上的选项:
package example;
import java.util.HashMap;
import java.util.Map;
public enum MenuOption implements Enumerable {
OPTION_ONE("Option One"),
OPTION_TWO("Option Two");
private static final Map<String, MenuOption> lookup = new HashMap<>();
private final String name;
static {
for (MenuOption option : MenuOption.values()) {
lookup.put(option.toString(), option);
}
}
private MenuOption(final String name) {
this.name = name;
}
public final static MenuOption getByName(final String name) {
return lookup.get(name);
}
public final String getName() {
return name;
}
}
这是 ParentMenu interface
的实现其中包含 SimpleMenu
作为子菜单。下面的 return 语句是我仍然收到“不兼容类型”错误的地方,因为 List<Enumerable>
与 List<MenuOption>
不兼容.
package example;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public final class ConfigureMenu implements ParentMenu<Enumerable,ConfigureMenu.ConfigureSubMenu> {
public static enum ConfigureSubMenu implements Enumerable {
SIMPLE_MENU("An Option");
private final String name;
private static final Map<String, ConfigureSubMenu> lookup = new HashMap<>();
static {
for (ConfigureSubMenu subMenu : ConfigureSubMenu.values()) {
lookup.put(subMenu.toString(), subMenu);
}
}
private ConfigureSubMenu(final String name) {
this.name = name;
}
public final String getName() { return name; }
public static ConfigureSubMenu getByName(String name) {
return lookup.get(name);
}
}
public final List<Enumerable> getSubMenuOptions(final ConfigureSubMenu subMenu) {
switch(subMenu) {
case SIMPLE_MENU:
List<MenuOption> options = new SimpleMenu().getOptions();
//This line causes the incompatible types error (List<Enumerable> is not compatible with List<MenuOption>)
return options;
default:
return new ArrayList<>();
}
}
}
如何更改我的通用 interfaces
的签名或者我的具体实现的签名,以便我可以摆脱这个错误,并且仍然有一个灵活的通用方法,可以返回父菜单包含的任何子菜单的选项?
注意:自从提出并回答这个问题以来,我已对其进行了多次编辑,以提高质量并明确我的问题和我想要的目标是什么。
最佳答案
Java 泛型可能有点棘手。您的方法返回 List<Enumerable>
这意味着“一个恰好保存 Enumerable 类型的列表”。您正在返回 List<MenuOption>
,这不是同一类型。相反,您应该定义 getSubMenuOptions
在父菜单中为 public List<? extends T> getSubMenuOptions(U subMenu);
,其中List<? extends T>
表示“包含实现 T 的某种类型的列表(在本例中为 Enumerable)”。在 ConfigureMenu
,方法实现应定义为 public final List<? extends Enumerable> getSubMenuOptions
.
关于使用泛型的更多有用的详细信息是 available here .
关于java - 如何使用 Java 泛型以便为返回类型为 List<Interface> 的方法返回 List<InterfaceImpl>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26315916/