Problem: I want to define a List of Tuple2 and apply the elements of the tuples to the following Java method:
<T extends Event> void addEventHandler(EventType<T> type,
EventHandler<? super T> handler)
The first element of the tuple is applied to type (EventType<T>), and the second element to handler (EventHandler<? super T>).
I need to be able to add every variant of EventType<T> and EventHandler<? super T> which can be applied to addEventHandler to the list and need to retrieve them as types that can be applied to addEventHandler.
Example to illustrate the use case:
val eventType1: EventType[KeyEvent] = EventType1()
val eventType2: EventType[MouseEvent] = EventType2()
val eventHandlers: List[???] = List(
(eventType1, (event: KeyEvent) => ...),
(eventType2, (event: MouseEvent) => ...))
eventHandlers.foreach(item => addEventHandler(item._1, item._2))
Sorry, I forgot that the type of the list must be a Tuple (EventType[T], EventHandler[_ >: T]), but this should not change your proposed solution, right?
But then why wouldn’t the subclass know the type of T - either because it’s hardwired to that type or because it has a generic parameter of its own to specify it?
Just to make sure: Is there one specific T for all elements of that list, or do you want to have a list of pairs with independent, arbitrarily varying event types? In this case, you’ll probably have to either drop generic parameters in general and switch to abstract type members, or look into some advanced type magic like HLists.
…but the types of T for the pairs can differ among elements of the list? Then there simply is no T and you’ll have to resort to mechanisms beyond generics. @BalmungSan has already posted a draft based on abstract type members. Similar, just a bit closer to the Java API (and thus more convoluted):
trait Eventful {
type E <: Event
type H >: E <: Event
val tp: EventType[E]
val hnd: EventHandler[H]
}
def addEventful(ef: Eventful): Unit = addEventHandler(ef.tp, ef.hnd)
eventHandlers.foreach(addEventful)
Yes, but it was OK if they are all just Event. My only requirement is, that I can add Tuples having any sub-type of Event and get out Tuples where the generic type is Event.
Since I apply the elements of the list to a method that requires T must extend Event it should accept as well Event itself.
In other words: I never need to access the element in the list with the actual type, if that makes sense.
…you could get away with List[(EventType[Event], EventHandler[Event])].
Java doesn’t offer this kind of covariance, though, so I fear you’ll still have to go with abstract type members (or some other workaround). There still is no shared T for the list elements.
I did not have the chance to try it out. I modified my original post so that everybody is on the same page and knows what my use case is and others can learn form what you all posted here, too
When I am home I will try your implementation for sure, thank you for your effort!