Ho diversi tipi di eventi, ad esempio:
abstract class Event {
static class KeyPress extends Event { ... }
static class KeyRelease extends Event { ... }
static class KeyHold extends Event { ... }
// ...
}
E molti ascoltatori che rispondono ad alcuni degli eventi di cui sopra registrandoli in un gestore di eventi. Attualmente è così:
abstract class AbstractListener {
Set<Class<? extends Event>> eventTypes;
protected abstract boolean respond(Event event);
}
class DownKeyListener exteneds AbstractListener {
DownKeyListener () {
// just prepares to register to receive these events. doesn't matter how exactly.
eventTypes.add(KeyPress.class);
eventTypes.add(KeyHold.class);
//no KeyRelease e.g.
}
boolean respond(Event event) {
if (event instanceof KeyPress)
return handleKeyPress(event);
else if (event instanceof KeyHold)
return handleKeyHold(event);
return false;
}
private boolean handleKeyPress(KeyPress e) { ... }
private boolean handleKeyHold(KeyHold e) { ... }
}
Ciò che non mi piace di questo è che non c'è nulla che forzi o controlli almeno la relazione tra gli eventi registrati e i controlli per loro e la gestione nel metodo di risposta. Questo continua a portare a bug degli sviluppatori. è anche un sacco di codice con instanceof
s per poco beneficio (direi).
Quindi penso di fare qualcosa di "intelligente" come questo: creare una mappa tra i tipi di evento e i gestori in modo che ogni evento registrato per la gestione abbia un gestore:
abstract class AbstractListener {
Map<Class<? extends Event>, Function<? extends Event, Boolean> map = new ...
// ^ doesn't ensure these event ^: are the same but at least
// that someone responds
// to ensure same event i can do
protected <T extends Event> void register(Class<T> event, Function<T, Boolean> function) {
map.put(event, function);
}
protected abstract boolean respond(Event event);
}
E poi:
class DownKeyListener exteneds AbstractListener {
DownKeyListener () {
Map.put(KeyPress.class, keyPressFunction);
Map.put(KeyHold.class, keyHoldFunction);
}
boolean respond(Event event) {
Function<? extends Event, Boolean> f = map.get(event.getClass());
return f == null ? false : f.apply(event);
}
Function<KeyPress, Boolean> keyPressFunction = event -> ...;
Function<KeyHold, Boolean> keyHoldFunction = event -> ...;
}
Ovviamente questo non funziona a causa dei farmaci generici. apply
dà un errore e capisco perché
The method apply(capture#4-of ? extends Event) in the type Function<capture#4-of ? extends Event,Boolean> is not applicable for the arguments (capture#5-of ? extends Event)
Non so come ottenere ciò che voglio funzionare correttamente. Alcune cose che avevo in mente:
- Trasmetti il risultato di
map.get
a qualcosa che assicuri che funzioni correttamente - Cambia il metodo
respond
come genericoprotected abstract <T extends Event> boolean respond(T event);
che dà l'errore simile:
The method apply(capture#3-of ? extends Event) in the type Function<capture#3-of ? extends Event,Boolean> is not applicable for the arguments (T)
Qualcuno ha un suggerimento su come ottenere ciò che voglio in qualche modo?