I am implementing a GUI event system in Scala. I have something like:
case class EventObject
case class KeyEventObject extends EventObject
case class MouseEventObject extends EventObject
I would like to store event listener closures in a (multi-)map, like so:
var eventListeners = new MultiMap[EventDescriptor, (EventObject => Unit)];
My question is, is there some way to rewrite this so that the function signatures of the stored closure can be EventObject or any subclass? Something like the following:
var eventListeners = new MultiMap[EventDescriptor, [A <: EventObject](A => Unit)]
so that I can have the subtype known when I define the listener functions:
eventListeners.put(KEY_EVENT, (e:KeyEventObject) => { ... })
eventListeners.put(MOUSE_EVENT, (e:MouseEventObject) => { ... })
Not that many things are impossible. You can do the following, for example, with type classes:
And now:
It’s a little messy, but the usage is much prettier:
We can confirm that we can pick out individual kinds of event handlers:
And we can pretend to fire an event and run all the handlers for it:
And it’s all perfectly safe, since nothing gets into the underlying loosely-typed map without the proper evidence. We’d get a compile-time error if we tried to add a function from
StringtoUnit, for example.