web-dev-qa-db-fra.com

Générer des Enums Dynamiquement

Disons que j'ai un fichier au format XML de base, comme suit:

<?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>

et je voulais transformer SomeEnum en quelque chose comme ceci au moment de l'exécution:

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

... puis transmettez l'énumération nouvellement créée SomeEnum autour de ma candidature. Comment pourrais-je réaliser quelque chose comme ça? Est-ce faisable?

12
Chris Cashwell

Ce que vous essayez de faire n'a pas beaucoup de sens. Les énumérations ne servent vraiment que pour le temps de compilation, car elles représentent un ensemble fixe de constantes. Au moment de l'exécution, quel serait le sens d'un enum généré dynamiquement - en quoi cela serait-il différent d'un objet simple? Par exemple:

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

Votre code XML peut être analysé dans des objets Salutation nouvellement instanciés, qui peuvent être stockés dans une variable Collection ou utilisés autrement par votre programme. Notez que dans mon exemple, j'ai limité la création de Salutation en lui attribuant un constructeur private. Dans ce cas, le seul moyen de récupérer des instances consiste à appeler la méthode factory qui utilise votre code XML. Je crois que cela réalise le comportement que vous recherchez.

17
Paul Bellora

En fait, il est est possible de créer des instances enum de manière dynamique, mais c’est un hack total, je ne le conseillerais pas du tout. Peut-être vous méprenez-vous sur la nature d’un enum, c’est une fonctionnalité de compilation du langue, et vous n'êtes pas censé ajouter/supprimer des instances au moment de l'exécution.

Quoi qu'il en soit, si le hack pour la création dynamique d'instances enum vous intéresse, jetez un oeil à cet article article .

7
Óscar López

D'accord avec Oscar Lopez. Voici ce que j'ai fait, une sorte de bidouille.

public static enum Setter {

    DYNAMIC_ENUM_EXAMPLE {

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

Vous pouvez obtenir la valeur comme ceci: 

Setter.DYNAMIC_ENUM_EXAMPLE.setGetValue("namaste")

Sortie:

prefix namaste postfix
1
Gagan

Dynamic Enums est la réponse à votre problème:

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

Cette classe a une signature similaire à la classe standard Enum. Il possède un constructeur protégé pour permettre la création d'instances dans des classes Enum concrètes. Par exemple:

public class YesNo extends DEnum<YesNo> {

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

La classe DEnum connaît les noms des membres par introspection:

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

Il existe un getter dactylographié qui récupère tous les éléments:

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

Il permet d’ajouter des membres dynamiquement au moment de l’exécution avec (depuis la base de données ou depuis le fichier):

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

Qui ont le même comportement que les membres statiques: 

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