I am trying to create a sort of event bus that can handle multiple different events and their listeners.
The goal is that every event would inherit from a super Event class, the event bus would register that event, and listeners could subscribe to it.
This is probably easier to explain in code:
Event class and possible subclasses
public class Event
{
public final String eventName;
public final long timestamp;
public Event(String name, long time)
{
this.eventName = name;
this.timestamp = time;
}
}
public class UpdateEvent extends Event
{
public final double delta;
public UpdateEvent(double delta)
{
super("Event.Update", currentTime);
this.delta = delta;
}
}
public class FileUpdatedEvent extends Event
{
public final File file;
public FileUpdatedEvent(File file)
{
super("Event.FileUpdated", CurrentTime);
this.file = file;
}
}
EventBus class
public class EventBus
{
private Map<Class<? extends Event>, List<MonoCallback<? extends Event>> eventListeners = new HashMap<>();
public <E extends Event> void registerEventListener(Class<E> clazz, MonoCallback<E> listener)
{
List<MonoCallback<E> list = eventListeners.get(clazz);
list.add(listener);
}
public <E extends Event> void pushEvent(E event)
{
list<MonoCallback<E> list = eventListeners.get(event.getClass());
for(MonoCallback<E> listener : list)
{
listener.invoke(event);
}
}
}
Listener
public class SomeClass
{
public SomeClass()
{
instance_of_eventbus.registerEventListener(FileUpdatedEvent.class, (event) -> {
File file = event.file;
//do stuff
}
}
}
Obviously, the above lacks any sort of polish with null checks and what not, and… of course all fails. But hopefully you understand the point.
So my question is,
First; is there a way to enforce that the Class key and generic parameter in MonoCallback in the eventListeners map are the same?
Second; when the callback is invoked, that the passed event parameter is ensured to be an instance of the proper Event subclass, not requiring instanceof checks and casting on the listener end? (SomeClass example)
I have been messing around with this for quite some time, and have not come to a satisfactory solution, and any online research is so jumbled and confusing that it makes my head hurt.
For the record… I hate generics :-\