2011-12-11 10 views
12

Diciamo che ho un file il cui formato è XML di base, in questo modo:Generazione enumerazioni dinamicamente

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

e volevo trasformare SomeEnum in qualcosa di simile a runtime:

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

.. e quindi passare l'enum appena creato SomeEnum intorno alla mia applicazione. Come potrei ottenere qualcosa di simile? È fattibile?

risposta

14

Quello che stai cercando di fare non ha molto senso. Enums sono in realtà solo a beneficio del tempo di compilazione, in quanto rappresentano un insieme fisso di costanti. In fase di esecuzione, quale sarebbe il significato di un enum generato dinamicamente - come sarebbe diverso da un oggetto semplice? Per esempio:

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

tuo XML potrebbe essere analizzato in appena istanziati Salutation oggetti, che possono essere memorizzati in un certo Collection o altrimenti utilizzati dal programma. Nota nel mio esempio, ho limitato la creazione di Salutation dandogli un costruttore private - in questo caso l'unico modo per recuperare le istanze è chiamando il metodo factory che prende il tuo XML. Credo che questo raggiunga il comportamento che stai cercando.

+0

ha un senso. Ho chiesto specificamente enumerazioni perché la mia gerarchia ne ha troppe ora (non una cifra assurda, solo più di poche) e speravo di eliminarle. –

+0

@Chris - Aspetta, quindi la tua domanda sulla generazione del codice o sulla sua creazione in fase di runtime? –

+0

In realtà si tratta di crearli in fase di runtime. Suppongo che sia diverso. –

6

realtà è possibile creare istanze enum in modo dinamico, ma è un hack totale, non vi consiglio a tutti - forse stai fraintendendo la natura di un enum, è una caratteristica in fase di compilazione della lingua e non è necessario aggiungere/rimuovere istanze da esso in fase di runtime.

In ogni caso, se sei interessato all'hack per creare dinamicamente istanze enum, dai un'occhiata a questo article.

0

D'accordo con Oscar Lopez. Ecco cosa ho fatto, una sorta di hack.

public static enum Setter { 

    DYNAMIC_ENUM_EXAMPLE { 

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

è possibile ottenere il valore in questo modo:

Setter.DYNAMIC_ENUM_EXAMPLE.setGetValue("namaste") 

uscita:

prefix namaste postfix 
0

Enums dinamica è la risposta al vostro problema:

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

Questa classe ha una firma simile allo standard Enu m classe. Ha un costruttore protetto per consentire la creazione di istanze in classi Enum concrete.Per esempio:

public class YesNo extends DEnum<YesNo> { 

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

La classe DEnum conosce i nomi dei membri di introspezione:

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

C'è un getter digitato che recupera tutti gli elementi:

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

Permette di aggiungere membri dinamicamente in fase di esecuzione con (dal database o dal file):

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

che hanno lo stesso comportamento come i membri statici:

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

Dovresti includere un link all'implementazione di 'DEnum', o pubblicarlo qui –