2012-01-04 2 views
21

Это не вопрос того, что я застрял, но я ищу аккуратный способ написать свой код.Enum in enum

По существу, я пишу приложение, управляемое событиями. Пользователь запускает событие, событие отправляется соответствующим объектам, а объекты обрабатывают события. Теперь я работаю над написанием методов четного обработчика, и я надеялся использовать инструкции switch, чтобы определить, как обрабатывать событие. Прямо сейчас, пока я работаю на общей структуре, класс событий очень прост:

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

Затем, в другом классе, у меня будет что-то вроде:

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

Что бы как сделать, это что-то вроде этого (хотя я, конечно, придерживаться переключающих заявлений в свои собственные функции, чтобы избежать его превращения в неприятную Hairball выключателей и случаев):

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

Итак, я хочу, чтобы создать вложенные перечислений ... как так:

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

Это не так, как я не могу избежать сценария, было бы просто ... удобно. Итак, хотя вышеупомянутое на самом деле не работает, существует ли какой-то подобный метод для достижения этого? Было бы неплохо, если бы я мог отправить событие с действием «MOVE.UP», и этот метод сначала идентифицировал бы его как действие типа MOVE, а затем еще раз определит, что он конкретно находится в направлении UP. Это просто простой пример, было бы ужасно, если бы я мог также создавать более длинные цепочки, что-то вроде «DELETE.PAGE1.PARAGRAPH2.SENTENCE2.WORD11.LETTER3». То, как я это вижу, мне просто придется использовать строки и множество операторов if/else. Надеюсь, есть лучший способ! (О, и производительность имеет значение в моем случае, если это помогает)

+1

Я бы не использовал перечисление для описания ваших событий вообще. Перечисления лучше всего для счетного, постоянного набора состояний. UP, DOWN, LEFT, RIGHT хороши, потому что вряд ли они изменятся. MOVE, FOO, BAR чувствует, что это должно быть легко добавить. Вместо этого я бы использовал полиморфизм. (Каждое событие, реализующее doSomething, которое принимает состояние игры). – ILMTitan

ответ

7

Возможно, используйте иерархию наследования для событий?

Так у вас есть:

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

Это может иметь больше смысла иметь:

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

Если все двигают события имеют расстояние, а затем передать, что в конструктор MoveEvent (который будет пульсация вниз).

22

Я считаю, что в Java вы можете просто вложить перечисления, пока ваши константы не-enum на первом месте.

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

Это компилируется для меня и дает мне поведение, которое вы искали.

+6

интересный. и MOVE не является действием. Action.values ​​() имеет только FOO и BAR –

+0

Хотя, Action.MOVE.UP полностью действует –

+2

да, но вам нужно это знать. нет возможности легко проходить через все экземпляры перечисления. –

2

вы можете вложить их в произвольном порядке, как это:

пакет вложенным;

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