简体   繁体   English

结合枚举并使用getter返回指定的枚举

[英]Combining enums and using getter to return a specified enum

Let's say I have 2 different sets of enums: fruits and vegetables. 假设我有2种不同的枚举:水果和蔬菜。

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

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

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

I display all this in a JComboBox. 我在JComboBox中显示所有这些。 After someone selects something, I want to use a getter method to get back the Enum. 在某人选择了某些内容后,我想使用getter方法来获取Enum。

For a single enum, I would do something like: 对于单个枚举,我会做类似的事情:

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

Any ideas what the return type is? 任何想法返回类型是什么? I tried using Enum instead of Fruits. 我尝试使用Enum而不是Fruits。 When I do that, I don't seem to have access to the getName() methods. 当我这样做时,我似乎无法访问getName()方法。

Here is another demonstration of what you're looking for. 这是您正在寻找的另一个示范。 The difference between this and previous solutions is that this one is more generic and reusable pattern. 此解决方案与以前的解决方案之间的区别在于,此解决方案更通用且可重复使用。 This in fact goes beyond the original problem, to show some other benefits of this approach. 事实上这超出了原来的问题,显示了这种方法的一些其他好处。 So you might just comment the bits you don't need. 所以你可能只是评论你不需要的位。 I also attach a unit test to demonstrate the behaviour. 我还附上一个单元测试来证明行为。

So basically to look for name Apple or APPLE in one of these enums just write: 所以基本上只需要在其中一个枚举中查找名称AppleAPPLE

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

FruitVeg<> is an interface, which allows to also tap inside of Enum, this interface allows to do some very interesting things with enums below. FruitVeg<>是一个界面,它允许点击Enum内部,这个界面允许用下面的枚举做一些非常有趣的事情。 Here are just some of the things you could do with that: 以下是您可以做的一些事情:

  • Enum.valueOf(fvg.getDeclaringClass(), fvg.name()) : returns enum Value eg APPLE Enum.valueOf(fvg.getDeclaringClass(), fvg.name())返回枚举值,例如APPLE

  • fvg.getRaw() : returns enum Value eg APPLE fvg.getRaw()返回枚举值,例如APPLE

  • fvg.name() : returns enum's String Name eg APPLE fvg.name()返回枚举的字符串名称,例如APPLE

  • fvg.getFriendlyName() : eg Apple fvg.getFriendlyName() :例如Apple

  • fvg.getDeclaringClass() : returns Class<Enum<?>> eg class ox.dummy.dummyTest$Fruits fvg.getDeclaringClass()返回 Class<Enum<?>>例如class ox.dummy.dummyTest $ Fruits

  • fvg.getClass() : class ox.dummy.dummyTest$Fruits returns Class<?> fvg.getClass()class ox.dummy.dummyTest $ Fruits 返回 Class<?>

  • EnumSet.allOf(fvg.getDeclaringClass())) : eg [APPLE, PEAR] EnumSet.allOf(fvg.getDeclaringClass())) :例如[APPLE,PEAR]

Here is code 这是代码

   @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;
}

Option 1. 选项1。
Create one method that returns Enum 创建一个返回Enum的方法

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;
}

and to get the name of enum you can use this method 要获取枚举的名称,您可以使用此方法

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;
}

Option 2. 选项2。
You can combine 2 enum as 你可以将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()
    ... 
}

Pass in the Enums themselves as values. 将Enums本身作为值传递。 Then use getSelectedItem to retrieve the selected object, and do a test to see what type the object is. 然后使用getSelectedItem检索所选对象,并进行测试以查看该对象的类型。

Make the return type of your method an Object, not an enum of a specific type. 使方法的返回类型为Object,而不是特定类型的枚举。 This would fix your problem. 这将解决您的问题。

However, I think your approach is wrong. 但是,我认为你的做法是错误的。 If I wanted fruits and vegetables displayed in a list and broken into categories, I'd create an object to do so, and an enum to represent type of food like so: 如果我想在列表中显示水果和蔬菜并分类,我会创建一个这样做的对象,以及一个表示食物类型的枚举:

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);

And only add Food items to your JComboBox. 并且只将Food项添加到您的JComboBox。 Return Food items when a selection is made, and test for food type using the FoodType enum. 在做出选择时返回Food项目,并使用FoodType枚举测试食物类型。

It sounds like what you're looking for is the ability to apply inheritance to enums , but this is not possible in java, as enums implicity extend java.lang.Enum and java does not support multiple inheritance. 听起来你正在寻找的是将继承应用于enums的能力,但这在java中是不可能的,因为enums implicity扩展了java.lang.Enum并且java不支持多重继承。

Nonetheless, I think that using " nested enums " could solve your problem. 尽管如此,我认为使用“ 嵌套枚举 ”可以解决您的问题。 By nested, I mean implementing an interface to get around the multiple inheritance issue. 通过嵌套,我的意思是实现一个接口来解决多重继承问题。 There are a few different approaches in the answers in the link, I assume one of them will suffice. 在链接的答案中有几种不同的方法,我假设其中一种就足够了。

You could use Object instead of explicitly using Fruit or Vegetables 您可以使用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;
}

Downside of this however is that you will then have to compare and cast the result to what you want 然而,这样做的缺点是,您必须比较并将结果转换为您想要的结果

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM