Given the following Scala 2.11 code:
class Partials {
class Aggregate
class AggregateId[T <: Aggregate]
class Event[T <: Aggregate]
type EventListener = PartialFunction[Event[_], Unit]
val listeners = mutable.Set[EventListener]()
def addListener(l: EventListener) {
listeners += l
}
def process(e: Event[_]): Unit = {
listeners.foreach(listener => if (listener.isDefinedAt(e)) listener.apply(e))
}
addListener {
case x => println(x)
}
}
This is simplified from my actual code, some event processing, but it shows the same issue. I have events that refer to some aggregate, and I have listeners that should be able to handle these events. The listeners are PartialFunctions so they could handle some Event subtypes but not all of them.
As listed, I'm getting the following error for the addListener call at the end:
type arguments [_$1] do not conform to class Event's type parameter bounds [T <: Partials.this.Aggregate]
addListener {
When I change the EventListener
type alias to
type EventListener = PartialFunction[Event[_ <: Aggregate], Unit]
I instead get the following errors in the process
method:
Error:(19, 60) type mismatch;
found : Partials.this.Event[_$2] where type _$2
required: Partials.this.Event[_ <: Partials.this.Aggregate]
listeners.foreach(listener => if (listener.isDefinedAt(e)) listener.apply(e))
Error:(19, 79) type mismatch;
found : Partials.this.Event[_$2] where type _$2
required: Partials.this.Event[_ <: Partials.this.Aggregate]
listeners.foreach(listener => if (listener.isDefinedAt(e)) listener.apply(e))
At the moment I don't really understand what is going on. Event
needs its type parameter for things unrelated to this, but for the PartialFunctions that are supposed to handle events, I'd like to simply ignore that type parameter, which is what I thought I did with the [_]
. What am I getting wrong?
This seems to work:
import scala.collection.mutable
class Partials {
class Aggregate
class AggregateId[T <: Aggregate]
class Event[T <: Aggregate]
type EventListener = PartialFunction[Event[_ <: Aggregate], Unit]
val listeners = mutable.Set[EventListener]()
def addListener(l: EventListener) {
listeners += l
}
def process(e: Event[_ <: Aggregate]) {
listeners.foreach(listener => if (listener.isDefinedAt(e)) listener.apply(e))
}
addListener {
case x => println(x)
}
}
Notice how process
method is defined. Those error messages were telling you that when you define listener
's type as PartialFunction[Event[_ <: Aggregate], Unit]
, then you need to pass instance of Event[_ <: Aggregate]
to listener
's isDefinedAt
and apply
methods.