[英]Generic interface with extends generic of Enums
我正在嘗試編寫一個通用的事件系統。 為此,我想像這樣為*創建一個EventHandler
接口(不起作用)*:
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);
}
但這不起作用,因為我“想”它。
事件本身是一個通用元素,它非常簡單:
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
id就像讓它仍然是通用的那樣有一些像DefaultHandler<GameEvent<TypeEnum, AttributEnum>>()
來初始化它。 因此,您可以使用Interface創建自己的處理程序或使用我提供的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
那我該怎么辦? 是否有可能像我想擁有它?
說實話,我不確定我是否完全理解你的要求。 但是如果你想讓DefaultGameEventHandler盡可能通用,我建議采用以下方法:
而不是讓接受Enums作為通用EventTypes和AttributeTypes的GameEventHandler接口,使GameEventHandler接口接受EventType接口和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;}
}
現在,您可以創建一個實現GameEventHandler接口的通用DefaultGameEventHandler類:
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;
}
編輯 - 回復BennX的評論:
我認為,定義帶有2個枚舉的Eventhandlers和GameEvents是相當不錯的。 但我認為只有你已標記的枚舉才有可能。
實際上我不想表明,使用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>
但為什么強迫Enums對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,仍將使用此通用GameEventHandler。 但是,除了Enums之外,用戶還可以決定對事件和屬性類型使用最終的整數,最終字符串或任何其他對象。
我認為你必須使用DefaultGameEventHandler
如:
class DefaultGameEventHandler<TYPE extends Enum<?>,ATT extends Enum<?>> implements GameEventHandler<GameEvent<TYPE, ATT>,TYPE,ATT>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.