2014-02-20 3 views
3

Я пытаюсь написать общую систему событий. Для этого я хотел бы создать интерфейс для EventHandler как этот * (не работы) *:Общий интерфейс с расширением generic Enums

public interface GameEventHandler<I extends GameEvent<TYPE extends Enum<?>, ATT extends Enum<?>>> { 
    public void handleEvent(final GameEvent<TYPE, ATT>... e); 
    public void registerListener(final GameEventListener<I> listener, 
      final TYPE... type); 
    public void unregisterListener(final GameEventListener<I>... listener); 
    public void unregisterAllListener(); 
    public void unregisterAllListener(final I... type); 
    public void processEvents(); 
    public void processEvents(final int maxTimeInMS); 
} 

, но это не работает, как я «думаю» это.

Само событие представляет собой универсальный элемент, который preaty просто так:

public class GameEvent<T extends Enum<?>, S extends Enum<?>> { 
    private HashMap<S, String> values; 
    private T type; 

    public void init(T type) { 
     this.type = type; 
    } 

    public T getType() { 
     return this.type; 
    } 

    public void addMessage(S t, String value) { 
     this.values.put(t, value); 
    } 

    public void getMessage(S t) { 
     this.values.get(t); 
    } 
} 

если я реализовать HandlerInterface ид нравится иметь это еще родовое так что есть что-то вроде DefaultHandler<GameEvent<TypeEnum, AttributEnum>>() инициализировать его. Таким образом, вы можете использовать интерфейс для создания своего собственного обработчика или использовать DefaultHandler, который я предоставляю, но все же могу использовать свой собственный Enums.

На данный момент я был в состоянии создать интерфейс, как это:

public interface GameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE extends Enum<?>, ATT extends Enum<?>> 

Но я не получаю внедрение DefaultHandler Generic

public class DefaultGameEventHandler implements GameEventHandler<GameEvent<EventTypes, AttributeTypes>, EventTypes, AttributeTypes> // not generic those are testing Enums 

Так что же я сделал не так? Возможно ли, что я хотел бы иметь его?

ответ

1

Честно говоря, я не уверен, если я полностью понимаю ваши требования.Но если вы хотите сделать свой DefaultGameEventHandler, как родовой, как это возможно, я хотел бы предложить следующий подход:

Вместо того, чтобы иметь интерфейс GameEventHandler, который принимает перечисления как родовое EventTypes и AttributeTypes, сделать интерфейс GameEventHandler принять интерфейс типСобытия и AttributeType интерфейс:

public interface GameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE extends EventType, ATT extends AttributeType> { 

    public void handleEvent(final GameEvent<TYPE, ATT>... e); 
    public void registerListener(final GameEventListener<I> listener, final TYPE... type); 

    public void unregisterListener(final GameEventListener<I>... listener); 

    public void unregisterAllListener(); 
    public void unregisterAllListener(final I... type); 

    public void processEvents(); 
    public void processEvents(final int maxTimeInMS); 

} 

Вот соответствующие интерфейсы и класс GameEvent:

public interface EventType { 
    // common functionality of EventTypes, if any 
} 

public interface AttributeType { 
    // common functionality of AttributeTypes , if any 
} 

public class GameEvent<T extends EventType, S extends AttributeType> { 
    private HashMap<S, String> values; 
    private T type; 

    public void init(T type) { 
     this.type = type; 
    } 

    public T getType() { 
     return this.type; 
    } 

    public void addMessage(S t, String value) { 
     this.values.put(t, value); 
    } 

    public void getMessage(S t) { 
     this.values.get(t); 
    } 
} 

Вы можете создать любое количество Перечисления, которые реализуют эти Интерфейсы:

enum MyEventTypes implements EventType{TYPE_1,TYPE_2,TYPE_3} 

enum MyAttributeTypes implements AttributeType{ATT_1,ATT_2,ATT_3} 

Если вам абсолютно необходимы интерфейсы для обеспечения функциональности из класса Enum, вы можете указать это в интерфейсе, как так:

public interface EventType { 
    Enum<?> asEnum(); 
} 

enum MyEventTypes implements EventType{ 
    TYPE_1,TYPE_2,TYPE_3; 
    @Override 
    public Enum<?> asEnum() {return this;} 
} 

Теперь вы можете создать общий класс DefaultGameEventHandler что реализует интерфейс GameEventHandler:

public class DefaultGameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE extends EventType, ATT extends AttributeType> implements GameEventHandler<I, TYPE, ATT>{ 

    @Override 
    public void handleEvent(GameEvent<TYPE, ATT>... e) { 
     //... 
    } 
    @Override 
    public void registerListener(GameEventListener<I> listener, TYPE... type) { 
     //... 
    } 
    @Override 
    public void unregisterListener(GameEventListener<I>... listener) { 
     //... 
    } 
    @Override 
    public void unregisterAllListener() { 
     //... 
    } 
    @Override 
    public void unregisterAllListener(I... type) { 
     //... 
    } 
    @Override 
    public void processEvents() { 
     //... 
    } 
    @Override 
    public void processEvents(int maxTimeInMS) { 
     //... 
    } 
} 

Вы можете создать экземпляр в DefaultGameEventHandler с перечислениями

//MyEventTypes and MyAttributeTypes are enums implementing EventType respectively AttributeType 
DefaultGameEventHandler<GameEvent<MyEventTypes, MyAttributeTypes>, MyEventTypes, MyAttributeTypes> handler = new DefaultGameEventHandler<>(); 
GameEvent<MyEventTypes, MyAttributeTypes> event = new GameEvent<>(); 
event.addMessage(MyAttributeTypes.ATT_1, "some Message"); 
event.init(MyEventTypes.TYPE_1); 
handler.handleEvent(event); 
switch (event.getType()) { 
    case TYPE_1: 
     System.out.println("TYPE_1"); 
     break; 
    case TYPE_2: 
     System.out.println("TYPE_2"); 
     break; 
    case TYPE_3: 
     System.out.println("TYPE_3"); 
     break; 
    default: 
     break; 
} 

или также с интерфейсами или каких-либо классов, реализующих интерфейсы:

DefaultGameEventHandler<GameEvent<EventType, AttributeType>, EventType, AttributeType> handler = new DefaultGameEventHandler<>(); 
GameEvent<EventType, AttributeType> event = new GameEvent<>(); 
event.addMessage(MyAttributeTypes.ATT_1, "some Message"); 
event.init(MyEventTypes.TYPE_1); 
handler.handleEvent(event); 
EventType type = event.getType(); 
// To switch on the type you could use the asEnum() method 
// and cast the type to the corresponding enum if possible: 
if (type.asEnum().getClass() == MyEventTypes.class) { 
    MyEventTypes t = (MyEventTypes)type.asEnum(); 
    switch (t) { 
     case TYPE_1: 
      System.out.println("TYPE_1"); 
      break; 
     case TYPE_2: 
      System.out.println("TYPE_2"); 
      break; 
     case TYPE_3: 
      System.out.println("TYPE_3"); 
      break; 
     default: 
      break; 
    } 
} 
// Or you could also directly switch on the name of the enum (not recommended!): 
switch (type.asEnum().name()) { 
    case "TYPE_1": 
     System.out.println("TYPE_1"); 
     break; 
    case "TYPE_2": 
     System.out.println("TYPE_2"); 
     break; 
    case "TYPE_3": 
     System.out.println("TYPE_3"); 
     break; 
    default: 
     break; 
} 

EDIT - В ответ на комментарий от BennX:

Я думаю, что было бы довольно хорошо, чтобы определить Eventhandlers и GameEvents с 2 Enums. Но я думаю, что это невозможно с перечислениями, как вы уже отметили.

На самом деле я не хотел указывать, что использование Enums невозможно. Вы можете полностью заменить интерфейсы в моих примерах с Перечисления, если вы хотите:

public class GameEvent<T extends Enum<?>, S extends Enum<?>> 

public interface GameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE extends Enum<?>, ATT extends Enum<?>> 

public class DefaultGameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE extends Enum<?>, ATT extends Enum<?>> implements GameEventHandler<I, TYPE, ATT> 

Но почему сила Перечисления на конечных пользователей GameEventHandler? Если вам не нужны какие-либо общие функциональные возможности в вашем EventType и AttributeType, то вы можете даже обойтись без каких-либо перечислений или интерфейсов на всех и сделать GameEventHandler полностью родовым:

public interface GameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE, ATT> 

public class GameEvent<T, S> 

public class DefaultGameEventHandler<I extends GameEvent<TYPE, ATT>, TYPE, ATT> implements GameEventHandler<I, TYPE, ATT> 

В примере кода я писал выше, где один экземпляр DefaultGameEventHandler с Enums, по-прежнему будет работать с этим универсальным GameEventHandler. Но вместо Enums пользователь также может решить использовать конечные целые числа, конечные строки или любой другой объект для типов событий и атрибутов.

+0

Я пытаюсь создать интерфейсы, которые позволят кому-то создавать «EventHandler», как он хочет, но также обеспечивают для него своего рода ориентир. (Эти интерфейсы) Id нравится доказывать обработчик по умолчанию, который уже создает нажатие всех событий зарегистрированным слушателям при вызове процессов. Я думаю, что было бы неплохо определить «Eventhandlers» и «GameEvents» с 2 «Enums». Но я думаю, что это невозможно только с перечислениями, как вы уже отметили. – BennX

+0

@BennX Я ответил на ваш комментарий в конце моего ответа. – Balder

+0

Вы указали на некоторые действительно хорошие вещи, и это действительно работает. Спасибо за помощь и спасибо за этот отличный ответ! Может быть, еще один намек. Как избавиться от предупреждений Supprest в интерфейсах, например, в этом: 'public void registerListener (final GameEventListener прослушиватель, \t \t \t final TYPE ... type);'? – BennX

-1

Я думаю, что вы должны пойти с DefaultGameEventHandler как:

class DefaultGameEventHandler<TYPE extends Enum<?>,ATT extends Enum<?>> implements GameEventHandler<GameEvent<TYPE, ATT>,TYPE,ATT> 
Смежные вопросы