2012-01-04 20 views
21

Non è una questione di me essere bloccato, ma piuttosto sto cercando un modo ordinato per scrivere il mio codice.Enum all'interno di una enum

In sostanza, sto scrivendo un'applicazione basata su eventi. L'utente attiva un evento, l'evento viene inviato agli oggetti appropriati e gli oggetti gestiscono gli eventi. Ora sto lavorando alla scrittura dei metodi di gestore pari, e speravo di usare le istruzioni switch per determinare come gestire l'evento. Proprio ora, mentre sto lavorando sulla struttura generale, la classe di evento è davvero semplice:

public class Event { 

    public static enum Action { 
     MOVE, FOO, BAR 
    } 

    private Action action; 
    private int duration; 

    public Event(Action action, int duration) { 
     this.action = action; 
     this.duration = duration; 
    } 

    public Action getAction() { 
     return action; 
    } 

    public int getDuration() { 
     return duration; 
    } 

Poi, in un'altra classe, avrò qualcosa di simile:

public void handleEvent(Event evt) {  
    switch(Event.getAction()) { 
     case MOVE: doSomething(); break; 
     case FOO: doSomething(); break; 
     case BAR: doSomething(); break; 
     default: break; 
    } 
} 

cosa avrei come fare è qualcosa di simile (anche se mi sarebbe naturalmente attaccare le istruzioni switch nelle proprie funzioni per evitare che si trasformi in una brutta palla di pelo di interruttori e dei casi):

public void handleEvent(Event evt) {  
    switch(Event.getAction()) { 
     case MOVE: switch(Event.getAction()) { 
         case UP: break; 
         case DOWN: break; 
         case LEFT: break; 
         case RIGHT: break; 
        } 
     case FOO: break; 
     case BAR: break; 
     default: break; 
    } 
} 

Quindi, vorrei creare enumerazioni nidificate ... in questo modo:

public static enum Action { 
    public enum MOVE {UP, DOWN, LEFT, RIGHT}, FOO, BAR 
} 

Non è che non riesco a evitare lo scenario, sarebbe solo ... conveniente. Quindi, mentre quanto sopra non funziona, c'è qualche metodo simile per raggiungere questo obiettivo? Sarebbe bello se potessi inviare un evento con l'azione "MOVE.UP", e il metodo identificherebbe prima come un'azione di tipo MOVE, e quindi identificherò ulteriormente che è specificamente nella direzione UP. Questo è solo un semplice esempio, sarebbe bello se potessi anche creare catene più lunghe, qualcosa come "DELETE.PAGE1.PARAGRAPH2.SENTENCE2.WORD11.LETTER3". Per come la vedo io, dovrò usare le stringhe e un sacco di istruzioni if ​​/ else. Sperando ci sia un modo migliore! (Oh, e le prestazioni sono importanti nel mio caso, se questo aiuta)

+1

Non userei un enum per descrivere i tuoi eventi. Le enumerazioni sono le migliori per un insieme numerabile e costante di stati. SU, GIÙ, SINISTRA, DESTRA è buono perché è improbabile che cambi. MOVE, FOO, BAR si sente come dovrebbe essere facile da aggiungere a. Invece userei il polimorfismo. (Ogni evento che implementa un doSomething che assume lo stato del gioco). – ILMTitan

risposta

7

Forse utilizzare una gerarchia di ereditarietà per gli eventi?

Così si hanno:

- abstract Event 
-- MoveEvent(Direction) 
-- FooEvent() 
-- BarEvent() 

Si può rendere più senso avere:

- abstract Event 
-- abstract MoveEvent 
--- MoveUpEvent 
--- MoveDownEvent 
--- MoveRightEvent 
--- MoveLeftEvent 
-- FooEvent 
-- BarEvent 

Se tutti gli eventi di spostamento hanno una distanza, quindi passare che nel costruttore MoveEvent (che sarà ondulazione giù).

22

Credo che in Java, puoi semplicemente annidare le enumerazioni, purché le costanti non enum vengano prima.

enum Action 
{ 
    FOO, 
    BAR; 
    enum MOVE 
    { 
     UP, 
     DOWN, 
     LEFT, 
     RIGHT 
    } 
} 

Questo compila per me e mi dà il comportamento che stavi cercando.

+6

interessante. e MOVE non è un'azione. Action.values ​​() ha solo FOO e BAR –

+0

Anche se, Action.MOVE.UP è totalmente valido –

+2

sì, ma è necessario saperlo. nessun modo per scorrere facilmente tutte le istanze di enum. –

2

si può loro nido in un ordine arbitrario come questo:

package annidato;

import java.util.*; 
import nested.Citrus.Orange; 
interface HasChildren { 
    Set<Enum<?>> children(); 
} 
enum Citrus implements HasChildren { 
    lemon, lime, orange; 
    Set<Enum<?>> children; 
    enum Orange implements HasChildren { 
     navel, valencia, blood; 
     Set<Enum<?>> children; 
     enum Navel implements HasChildren { 
      washinton, lateLane, caraCaraPink; 
      public Set<Enum<?>> children() { 
       return null; 
      } 
     } 
     static { 
      navel.children = new LinkedHashSet<Enum<?>>(); 
      navel.children.addAll(EnumSet.allOf(Navel.class)); 
     } 
     enum Blood implements HasChildren { 
      moro, taroco; 
      public Set<Enum<?>> children() { 
       return null; 
      } 
     } 
     static { 
      blood.children = new LinkedHashSet<Enum<?>>(); 
      blood.children.addAll(EnumSet.allOf(Blood.class)); 
     } 
     public Set<Enum<?>> children() { 
      return children != null ? Collections.unmodifiableSet(children) : null; 
     } 
    } 
    static { 
     orange.children = new LinkedHashSet<Enum<?>>(); 
     orange.children.addAll(EnumSet.allOf(Orange.class)); 
    } 
    public Set<Enum<?>> children() { 
     return children != null ? Collections.unmodifiableSet(children) : null; 
    } 
} 
public class EnumTreeNested { 
    static void visit(Class<?> clazz) { 
     Object[] enumConstants = clazz.getEnumConstants(); 
     if (enumConstants[0] instanceof HasChildren) for (Object o : enumConstants) 
      visit((HasChildren) o, clazz.getName()); 
    } 
    static void visit(HasChildren hasChildren, String prefix) { 
     if (hasChildren instanceof Enum) { 
      System.out.println(prefix + ' ' + hasChildren); 
      if (hasChildren.children() != null) for (Object o : hasChildren.children()) 
       visit((HasChildren) o, prefix + ' ' + hasChildren); 
     } else 
      System.out.println("other " + hasChildren.getClass()); 
    } 
    static <E extends Enum<E> & HasChildren> Set<E> foo() { 
     return null; 
    } 
    public static void main(String[] args) { 
     System.out.println(Citrus.Orange.Navel.washinton); 
     visit(Citrus.lemon, ""); 
     System.out.println("----------------------"); 
     visit(Citrus.orange, ""); 
     System.out.println("----------------------"); 
     visit(Citrus.class); 
     System.out.println("----------------------"); 
    } 
}