2013-07-15 132 views
7

假設我有兩組不同的枚舉:水果和蔬菜。結合枚舉和使用getter返回指定的枚舉

public static enum Fruits{ 
    APPLE ("Apple"), 
    PEAR ("Pear"); 

    //constructor 
    //getName() 
    ... 
} 
public static enum Vegetables{ 
    CARROT ("Carrot"), 
    LETTUCE ("Lettuce"); 

    //constructor 
    //getName() 
    ... 
} 

我在JComboBox中顯示所有這些信息。在某人選擇了某個東西后,我想使用getter方法取回Enum。

對於單個枚舉,我會做這樣的事情:

public static Fruits getEnum(String name) { 
    for(Fruits fruit: Fruits.values()) { 
    if(name.equals(fruit.getName())) { 
     return fruit; 
    } 
    } 
    return null; 
} 

任何想法的返回類型是什麼?我嘗試使用枚舉而不是水果。當我這樣做時,我似乎無法訪問getName()方法。

回答

0

這聽起來像你正在尋找的是能夠將繼承應用到enums,但這在java中是不可能的,因爲enums暗示擴展java.lang.Enum而java不支持多繼承。

儘管如此,我認爲使用「nested enums」可以解決您的問題。通過嵌套,我的意思是實現一個接口來解決多重繼承問題。在鏈接的答案中有幾種不同的方法,我假設其中的一個就足夠了。

3

選項1.
創建一個返回枚舉

public static Enum getEnum(String name) { 
    Enum selectedEnum = null; 
    for (Fruits fruit : Fruits.values()) { 
     if (name.equals(fruit.getName())) { 
      selectedEnum = fruit; 
     } 
    } 

    for (Vegetables vegetables : Vegetables.values()) { 
     if (name.equals(vegetables.getName())) { 
      selectedEnum = vegetables; 
     } 
    } 
    return selectedEnum; 
} 

,並讓你可以使用這個方法枚舉的名字一個方法

public static String getName(final Enum value) { 
    String name = null; 
    if (value instanceof Fruits) { 
     name = ((Fruits) value).getName(); 
    } else if (value instanceof Vegetables) { 
     name = ((Vegetables) value).getName(); 
    } 
    return name; 
} 

選項2
你可以結合使用2個枚舉作爲

public static enum FruitsAndVegitables{ 
    APPLE ("Apple" , true), 
    PEAR ("Pear", true), 
    CARROT ("Carrot", false), 
    LETTUCE ("Lettuce", false); 

    private String name; 
    private boolean isFurit; 
    //constructor 
    //getName() 
    ... 
} 
+0

因爲我不想給枚舉結合,我想我唯一的選擇是1 – dalawh

+0

@dalawh如果您發現有任何答案對你有幫助。然後upvote並接受這個答案,以便將來它會對別人有幫助。我發現你問了這麼多問題,但還沒有接受任何答案。因此,如果任何答案解決了您的問題,請接受該答案。 –

+0

所以沒有辦法在枚舉中獲得枚舉類型,而不必將枚舉組合起來? – dalawh

1

傳入Enums自己作爲值。然後使用getSelectedItem來檢索選定的對象,並進行測試以查看對象是什麼類型。

使方法的返回類型成爲對象,而不是特定類型的枚舉。這將解決您的問題。

但是,我認爲你的方法是錯誤的。如果我想的水果和在列表中顯示的蔬菜分爲兩類,我會創建一個對象來做到這一點,和一個枚舉來表示食品的類型,像這樣:

public enum FoodType{FRUIT, VEGETABLE} 
public class Food{ 
    FoodType type; 
    String name; 
    public Food(FoodType type, String name){ 
     this.type = type; 
     this.name = name; 
    } 
    public String toString(){return this.name;} 
} 

//and then when you want to use it... 
Food lettuce = new Food(FoodType.VEGETABLE, "Lettuce"); 
Food berry = new Food(FoodType.BERRY, "Berry"); 
comboBox.add(lettuces); 
comboBox.add(berry); 

而且只會增加Food項目到您的JComboBox中。在進行選擇時返回Food項目,並使用FoodType枚舉測試食物類型。

0

你可以使用Object而是明確使用FruitVegetables

public static Object getEnum(String name) 
{  
    for(Fruits fruit: Fruits.values()) 
    { 
     if(name.equals(fruit.getName())) 
     { 
       return fruit; 
     } 
    } 
    for(Vegetables vege: Vegetables.values()) 
    { 
     if(name.equals(Vegetables.getName())) 
     { 
       return vege; 
     } 
    } 
    return null; 
} 

這個壞處不過是你接下來要比較並將結果轉換到你想要

Object o = getEnum("Carrot") 
if(o instanceof Vegetable) 
{ 
    Vegetable v = (Vegetable)o; 
    v.getName(); 
} 
//.. and again for fruit 
+1

我希望我不必比較和投射結果。 – dalawh

+0

不幸的是,這個選項意味着我將不得不爲每個不同的枚舉創建if和else if語句,並且代碼的副本將不得不駐留在每個枚舉中。 – dalawh

15

這裏什麼是你正在尋找的另一個示範。這與以前的解決方案之間的區別在於,這個是更通用和可重用的模式。這實際上超出了原來的問題,以顯示這種方法的其他好處。所以你可能只是評論你不需要的部分。我還附上一個單元測試來演示行爲。

所以基本上找名AppleAPPLE這些枚舉一個只寫:

FruitVeg<?> fvg = getEnum("APPLE", Fruits.class, Vegetables.class);

FruitVeg<>是一個接口,它允許也枚舉的內部挖掘,該接口允許做一些下面的枚舉非常有趣的事情。這裏只是一些你可以與做的事情:

  • Enum.valueOf(fvg.getDeclaringClass(), fvg.name())返回枚舉值例如APPLE

  • fvg.getRaw()返回枚舉值例如APPLE

  • fvg.name()返回枚舉的字符串名稱例如APPLE

  • fvg.getFriendlyName()例如: 蘋果

  • fvg.getDeclaringClass()回報Class<Enum<?>>例如類ox.dummy.dummyTest $水果

  • fvg.getClass()類ox.dummy.dummyTest $水果回報Class<?>

  • EnumSet.allOf(fvg.getDeclaringClass())):例如[蘋果,梨]

這裏是代碼

@Test 
public void doSimpleTest() throws Exception { 

    FruitVeg<?> fvg = getEnum("APPLE", Fruits.class, Vegetables.class); 
    log.info("{} : {} : {} : {} : {}", fvg.name(), fvg.getFriendlyName(), fvg.getClass(), fvg.getDeclaringClass(), EnumSet.allOf(fvg.getDeclaringClass())); 
    log.info("get enum: {} ", Enum.valueOf(fvg.getDeclaringClass(), fvg.name())); 

} 


public interface FruitVeg<T extends Enum<T>> { 
    String name(); 

    String getFriendlyName(); 

    Class<T> getDeclaringClass(); 

    T getRaw(); 

} 

enum Fruits implements FruitVeg<Fruits> { 
    APPLE("Apple"), 
    PEAR("Pear"); 

    Fruits(String friendlyName) { 
     this.friendlyName = friendlyName; 
    } 

    private final String friendlyName; 

    @Override 
    public String getFriendlyName() { 
     return friendlyName; 
    } 
    @Override 
    public Fruits getRaw() { 
     return this; 
    } 
} 


enum Vegetables implements FruitVeg<Vegetables> { 
    CARROT("Carrot"), 
    LETTUCE("Lettuce"); 

    Vegetables(String friendlyName) { 
     this.friendlyName = friendlyName; 
    } 

    private final String friendlyName; 

    @Override 
    public String getFriendlyName() { 
     return friendlyName; 
    } 

    @Override 
    public Vegetables getRaw() { 
     return this; 
    } 
} 


public static FruitVeg<?> getEnum(String name, Class<? extends FruitVeg<?>>... fvgClasses) { 
    for (Class<? extends FruitVeg<?>> fruitVegCLass : Arrays.asList(fvgClasses)) { 
     for (FruitVeg<?> fvg : fruitVegCLass.getEnumConstants()) { 
      if (name.equals(fvg.name()) || name.equals(fvg.getFriendlyName())) { 
       return fvg; 
      } 
     } 
    } 
    return null; 
}