2012-01-04 9 views
21

No se trata de que yo esté atascado, sino que estoy buscando una forma ordenada de escribir mi código.Enumerar dentro de una enumeración

Básicamente, estoy escribiendo una aplicación impulsada por eventos. El usuario activa un evento, el evento se envía a los objetos apropiados y los objetos manejan los eventos. Ahora estoy trabajando en escribir los métodos de controlador par, y esperaba usar declaraciones de cambio para determinar cómo manejar el evento. Ahora mismo, mientras estoy trabajando en la estructura general, la clase de evento es muy simple:

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

Luego, en otra clase, voy a tener algo como:

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

lo que yo como que hacer es algo como esto (aunque me gustaría, por supuesto, se adhieren las sentencias switch en sus propias funciones para evitar que se convierta en una bola de pelo desagradable de interruptores y los casos):

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

Por lo tanto, yo quiero crear enumeraciones anidados ... de este modo:

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

No es que no puedo evitar el escenario, no sería más que conveniente .... Entonces, aunque lo anterior en realidad no funciona, ¿hay algún método similar para lograr esto? Sería bueno si pudiera enviar un evento con la acción "MOVE.UP", y el método lo identificaría primero como una acción de tipo MOVE, y luego identificaría que está específicamente en la dirección UP. Es solo un ejemplo simple, sería genial si también pudiera hacer cadenas más largas, algo así como "DELETE.PAGE1.PARAGRAPH2.SENTENCE2.WORD11.LETTER3". De la forma en que lo veo, tendré que usar cadenas y muchas declaraciones if/else. ¡Esperando que haya una mejor manera! (Ah, y el rendimiento importa en mi caso, si eso ayuda)

+1

No utilizaría una enumeración para describir sus eventos. Los mensajes son los mejores para un conjunto contable y constante de estados. Arriba, abajo, izquierda, derecha es bueno porque es poco probable que cambien. MOVE, FOO, BAR se siente como que debería ser fácil de agregar. En cambio, usaría polimorfismo. (Cada evento implementa un doSomething que toma el estado del juego). – ILMTitan

Respuesta

7

¿Quizás use una jerarquía de herencia para los eventos?

Así que tienes:

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

Se puede tener más sentido tener:

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

Si todos los eventos Move tienen una distancia, entonces sucederá que al constructor MoveEvent (que será rizo abajo).

22

Creo que en Java, simplemente puede anidar enums, siempre y cuando las constantes que no son enum sean lo primero.

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

Esto compila para mí y me da el comportamiento que estaba buscando.

+6

interesante. y MOVER no es una Acción. Action.values ​​() solo tiene FOO y BAR –

+0

Aunque, Action.MOVE.UP es totalmente válido –

+2

sí, pero debe saberlo. no hay forma de iterar fácilmente a través de todas las instancias enum. –

2

puede anidar en un orden arbitrario como esto:

paquete anidado;

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("----------------------"); 
    } 
} 
Cuestiones relacionadas