我有一个涉及嵌套枚举的数据结构,这样我就可以执行以下操作:
Drink.COFFEE.getGroupName();
Drink.COFFEE.COLUMBIAN.getLabel();
如果有方法声明:
someMethod(Drink type)
someOtherMethod(DrinkTypeInterface type)
然后我可以说(适当地):
someMethod(Drink.COFFEE)
someOtherMethod(Drink.COFFEE.COLUMBIAN)
这就是我提出的:
public enum Drink {
COFFEE("Coffee");
private String groupName;
private Drink(String groupName) {
this.groupName = groupName;
}
public enum Coffee implements DrinkTypeInterface {
COLUMBIAN("Columbian Blend"),
ETHIOPIAN("Ethiopian Blend");
private String label;
private Coffee(String label) {
this.label = label;
}
public String getLabel() {
return this.label;
}
}
String getGroupName() {
return this.groupName;
}
}
界面:
public interface DrinkTypeInterface {
public String getLabel();
}
我想我只是试着用Java来解决这种事情的最佳方法,或者如果我需要编写一堆if语句来处理单个Drink.values( )。有什么帮助吗?
答案 0 :(得分:35)
Drink.COFFEE.getGroupName();
Drink.COFFEE.COLUMBIAN.getLabel();
首先,您提供的示例代码在某种程度上违反了“demeter法则” - 因为COLUMBIAN实例字段仅用于检索标签。此外,使用该结构,COLUMBIAN 必须成为COFFEE枚举的实例,但我认为这不是你真正想要的。
someMethod(Drink type)
someOtherMethod(DrinkTypeInterface type)
someMethod(Drink.COFFEE)
someOtherMethod(Drink.COFFEE.COLUMBIAN)
我从你的样本中收集的是,你想要一个包含实际饮料的“组类型”的枚举,然后每个人都有特定类型饮料的个别值。你的例子给了咖啡,但茶应该也可以。
问题在于您如何放置枚举。正如我之前所说的那样,你必须让COLUMBIAN成为COFFEE枚举的实体,但这并不是构建它的最好方法。
问题是你有饮料,然后是咖啡/茶,然后是各自的类型。 但是,如果你考虑一下,虽然HerbalTea是一种茶,但它也是一种饮品 - 所以它不仅仅是TEA的一个例子。
但是,如果你将饮料输入本身就是一个枚举,你得到你想要的东西,结构就会变得更加清晰。由于接口和授权的强大,饮料类型和饮料枚举都可以以相同的方式处理,如下面的示例程序:
public final class DrinkEnumExample {
public interface DrinkTypeInterface {
String getDisplayableType();
}
public static enum DrinkType implements DrinkTypeInterface {
COFFEE("Coffee"), TEA("Tea");
private final String type;
private DrinkType(final String type) {
this.type = type;
}
public String getDisplayableType() {
return type;
}
}
public static enum Drink implements DrinkTypeInterface {
COLUMBIAN("Columbian Blend", DrinkType.COFFEE),
ETHIOPIAN("Ethiopian Blend", DrinkType.COFFEE),
MINT_TEA("Mint", DrinkType.TEA),
HERBAL_TEA("Herbal", DrinkType.TEA),
EARL_GREY("Earl Grey", DrinkType.TEA);
private final String label;
private final DrinkType type;
private Drink(String label, DrinkType type) {
this.label = label;
this.type = type;
}
public String getDisplayableType() {
return type.getDisplayableType();
}
public String getLabel() {
return label;
}
}
public DrinkEnumExample() {
super();
}
public static void main(String[] args) {
System.out.println("All drink types");
for (DrinkType type : DrinkType.values()) {
displayType(type);
System.out.println();
}
System.out.println("All drinks");
for (Drink drink : Drink.values()) {
displayDrink(drink);
System.out.println();
}
}
private static void displayDrink(Drink drink) {
displayType(drink);
System.out.print(" - ");
System.out.print(drink.getLabel());
}
private static void displayType(DrinkTypeInterface displayable) {
System.out.print(displayable.getDisplayableType());
}
}
该程序的输出如下:
All drink types
Coffee
Tea
All drinks
Coffee - Columbian Blend
Coffee - Ethiopian Blend
Tea - Mint
Tea - Herbal
Tea - Earl Grey
现在,如果由于某种原因你不想在一个单一的枚举中饮用所有饮料,那么我就不明白你的意思了。在这种情况下,如果您确实具有跨越枚举的功能,请制作单独的Coffee和Tea(以及其他)枚举,并在两个(或更多)枚举上应用该接口。但是,我认为你试图将它们分组。
答案 1 :(得分:12)
根据建议EnumSet
,考虑使用here收集不同类型的Drink
。
附录:作为一个具体的例子,下面的代码产生了显示的输出。
Coffee: Columbian Blend Coffee: Ethiopian Blend
代码:
public static enum DrinkType {
COFFEE("Coffee"), TEA("Tea");
private final String displayName;
private DrinkType(final String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
}
public enum Drink {
COLUMBIAN(DrinkType.COFFEE, "Columbian Blend"),
ETHIOPIAN(DrinkType.COFFEE, "Ethiopian Blend"),
MINT_TEA(DrinkType.TEA, "Mint"),
HERBAL_TEA(DrinkType.TEA, "Herbal"),
EARL_GREY(DrinkType.TEA, "Earl Grey");
public static Set<Drink> coffees = EnumSet.of(COLUMBIAN, ETHIOPIAN);
public static Set<Drink> teas = EnumSet.range(MINT_TEA, EARL_GREY);
private String groupName;
private String drinkName;
private Drink(DrinkType type, String drinkName) {
this.groupName = type.getDisplayName();
this.drinkName = drinkName;
}
public String getGroupName() {
return this.groupName;
}
public String getDrinkName() {
return drinkName;
}
}
public static void main(String... args) {
for (Drink d : Drink.coffees) {
System.out.println(d.getGroupName() + ": " + d.getDrinkName());
}
}
答案 2 :(得分:1)
我最近很好奇自己是否可以令人满意地做到这一点。这是我最终得到的解决方案,我认为其API也更接近问问者最初想要的枚举的树结构:
public interface Drink {
String groupName();
String label();
enum Coffee implements Drink {
COLUMBIAN("Columbian Blend"),
ETHIOPIAN("Ethiopian Blend");
private final String label;
Coffee(String label) {
this.label = label;
}
@Override
public String groupName() {
return "Coffee";
}
@Override
public String label() {
return label;
}
}
enum Tea implements Drink {
MINT("Mint"),
HERBAL("Herbal"),
EARL_GREY("Earl Grey");
private final String label;
Tea(String label) {
this.label = label;
}
@Override
public String groupName() {
return "Tea";
}
@Override
public String label() {
return label;
}
}
}
public static void main(String[] args) {
Drink choice = Drink.Tea.EARL_GREY;
System.out.println(choice.groupName()); // Tea
System.out.println(choice.label()); // Earl Grey
}
答案 3 :(得分:0)
你可以这样做:
enum dogs {
boxer, collie;
}
enum cats {
siamese, tom
}
enum Animal {
cat(cats.tom), dog(dogs.boxer);
Animal(Enum e) {
this.e = e;
}
Object[] subValues() {
return e.getDeclaringClass().getEnumConstants();
}
final Enum e;
}
public class Main {
public static void main(String[] args) {
for (Animal animal : Animal.values()) {
System.out.print(animal);
for (Object o : animal.subValues())
System.out.print(" " + o);
System.out.println();
}
}
}