11

果物と野菜の2つの異なる列挙型セットがあるとしましょう。

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

戻り値の型は何ですか? Fruits の代わりに Enum を使用してみました。これを行うと、getName() メソッドにアクセスできないようです。

4

5 に答える 5

20

これは、探しているものの別のデモンストレーションです。このソリューションと以前のソリューションの違いは、これがより一般的で再利用可能なパターンであることです。実際、これは元の問題を超えており、このアプローチの他の利点を示しています。そのため、必要のないビットをコメントするだけでかまいません。動作を実証するための単体テストも添付します。

したがって、基本的に名前を探す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(): クラスox.dummy.dummyTest $Fruitsなどを返します。 Class<Enum<?>>

  • fvg.getClass():クラス ox.dummy.dummyTest$Fruits が返す 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;
}
于 2013-11-04T22:50:12.433 に答える
3

オプション 1.
Enum を返すメソッドを 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()
    ... 
}
于 2013-07-15T03:43:23.020 に答える
1

Enum 自体を値として渡します。次に、 を使用getSelectedItemして選択したオブジェクトを取得し、テストを実行してオブジェクトのタイプを確認します。

メソッドの戻り値の型をObject、特定の型の列挙型ではなく にします。これで問題が解決します。

しかし、あなたのアプローチは間違っていると思います。果物と野菜をリストに表示してカテゴリに分けたい場合は、そのためのオブジェクトと、次のような食品の種類を表す列挙型を作成します。

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.FRUIT, "Berry");
comboBox.add(lettuces);
comboBox.add(berry);

Foodそして、あなたのにアイテムを追加するだけJComboBoxです。Food選択が行われたときにアイテムを返し、FoodType列挙型を使用して食品の種類をテストします。

于 2013-07-15T03:44:37.693 に答える
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
于 2013-07-15T03:47:52.490 に答える
0

あなたが探しているのは継承を に適用する機能のようですが、暗黙の拡張と Java は多重継承をサポートしていないため enums、これはJava では不可能です。enumsjava.lang.Enum

それにもかかわらず、「ネストされた列挙型」を使用すると問題を解決できると思います。ネストするとは、多重継承の問題を回避するためのインターフェイスを実装することを意味します。リンクの回答にはいくつかの異なるアプローチがありますが、そのうちの1つで十分だと思います。

于 2013-07-15T03:42:55.040 に答える