web-dev-qa-db-ja.com

列挙型の動的な生成

次のように、基本的なXML形式のファイルがあるとします。

<?xml version="1.0"?>
<enum-set>
    <enum>
        <name>SomeEnum</name>
        <values>
            <value>
                <name>SOMEVALUE</name>
                <displayText>This is some value</displayText>
             </value>
            ... more values ...
        </values>
    </enum>
    ... more enums ...
</enum-set>

実行時にSomeEnumを次のようなものにしたかったのです。

public enum SomeEnum implements HasDisplayText {
    SOMEVALUE("This is some value"),
    ... more values ...;

    private String displayText;

    SomeEnum(String displayText) {
        this.displayText = displayText;
    }

    @Override
    public String getDisplayText() {
        return displayText;
    }
}

...次に、新しく作成した列挙型SomeEnumをアプリケーションの周りに渡します。どうすればこのようなことを達成できますか?それは可能ですか?

16
Chris Cashwell

あなたがやろうとしていることは、あまり意味がありません。 Enums は、定数の固定されたセットを表すため、実際にはコンパイル時の利益のためだけです。実行時に、動的に生成される列挙型の意味は何でしょうか-これはプレーンオブジェクトとどのように異なりますか?例えば:

public class Salutation implements HasDisplayText {

   private String displayText;

   private Salutation(String displayText) {
       this.displayText = displayText;
   }

   @Override
   public String getDisplayText() {
       return displayText;
   }

   public static Collection<Salutation> loadSalutations(String xml) {
      //parse, instantiate, and return Salutations
   }
}

XMLは、新しくインスタンス化されたSalutationオブジェクトに解析され、Collectionに格納されるか、プログラムで使用されます。私の例では、Salutationの作成にprivateコンストラクターを指定して制限していることに注意してください。この場合、インスタンスを取得する唯一の方法は、XMLを取得するファクトリメソッドを呼び出すことです。私はこれがあなたが探している振る舞いを達成すると信じています。

21
Paul Bellora

実際には、列挙型インスタンスを動的に作成することは可能ですが、それは完全なハックであり、まったくアドバイスしません。 enumの場合、これは言語のコンパイル時の機能であり、実行時にインスタンスを追加/削除することは想定されていません。

とにかく、列挙型インスタンスを動的に作成するためのハックに興味がある場合は、この article を参照してください。

10
Óscar López

動的列挙はあなたの問題への答えです:

public abstract class DEnum<E extends DEnum<E>> implements Comparable<E>, Serializable {

このクラスには、標準のEnumクラスと同様の署名があります。具体的なEnumクラスでインスタンスを作成できるようにする保護されたコンストラクタがあります。例えば:

public class YesNo extends DEnum<YesNo> {

    public final static YesNo YES = new YesNo();
    public final static YesNo NO = new YesNo();

DEnumクラスは、内省によってメンバーの名前を知っています。

String name = YesNo.YES.getName();
YesNo yes = YesNo.get(YesNo.class, name);
assert (yes == YesNo.YES);

すべてのアイテムを取得する型付きゲッターがあります。

YesNo[] items = yes.getItems();
assert (items.length == 2);

(データベースまたはファイルから)実行時に動的にメンバーを追加できます。

YesNo maybe = getOrCreateIfNotExists(YesNo.class, "MAYBE");
items = yes.getItems();
assert (items.length == 3);

静的メンバーと同じ動作をします:

YesNo unknown = YesNo.get(YesNo.class, "MAYBE");
assert (unknown == maybe);

オスカー・ロペスに同意する。これが私がやったこと、一種のハックです。

public static enum Setter {

    DYNAMIC_ENUM_EXAMPLE {

        @Override
        public String setGetValue(String yourValue) {
            return "prefix " + yourValue + " postfix";
        }
    };
    public abstract String setGetValue(String value);
}

あなたはこのような値を得ることができます:

Setter.DYNAMIC_ENUM_EXAMPLE.setGetValue("namaste")

出力:

prefix namaste postfix
2
Gagan