Перечисление в перечислении
Это не вопрос того, что я застрял, но я ищу способ аккуратного написания кода.
По сути, я пишу приложение, управляемое событиями. Пользователь запускает событие, событие отправляется соответствующим объектам, а объекты обрабатывают события. Теперь я работаю над написанием методов четного обработчика, и я надеялся использовать инструкции 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;
}
}
То, что я хотел бы сделать, это что-то вроде этого (хотя я, конечно же, буду придерживаться операторов switch в своих собственных функциях, чтобы избежать превращения его в неприятный волокит переключателей и случаев):
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
Возможно, используйте иерархию наследования для событий?
Итак, у вас есть:
- abstract Event
-- MoveEvent(Direction)
-- FooEvent()
-- BarEvent()
Возможно, имеет смысл:
- abstract Event
-- abstract MoveEvent
--- MoveUpEvent
--- MoveDownEvent
--- MoveRightEvent
--- MoveLeftEvent
-- FooEvent
-- BarEvent
Если все события Move имеют расстояние, то передайте это в конструктор MoveEvent (который будет пульсировать вниз).
Ответ 2
Я считаю, что в Java вы можете просто вложить enums, пока ваши константы, отличные от enum, будут первыми.
enum Action
{
FOO,
BAR;
enum MOVE
{
UP,
DOWN,
LEFT,
RIGHT
}
}
Это компилируется для меня и дает мне поведение, которое вы искали.
Ответ 3
вы можете вложить их в произвольный порядок:
пакет вложен;
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("----------------------");
}
}