不可能なことはそれほど多くありません。たとえば、型クラスを使用して次のことを実行できます。
class HMultiMap {
import scala.collection.mutable.{ Buffer, HashMap }
type Mapping[K, V]
private[this] val underlying = new HashMap[Any, Buffer[Any]]
def apply[K, V](key: K)(implicit ev: Mapping[K, V]) =
underlying.getOrElse(key, Buffer.empty).toList.asInstanceOf[List[V]]
def add[K, V](key: K)(v: V)(implicit ev: Mapping[K, V]) = {
underlying.getOrElseUpdate(key, Buffer.empty) += v
this
}
}
そして今:
sealed trait EventObject
case class KeyEventObject(c: Char) extends EventObject
case class MouseEventObject(x: Int, y: Int) extends EventObject
sealed trait EventDescriptor
case object KEY_EVENT extends EventDescriptor
case object MOUSE_EVENT extends EventDescriptor
class EventMap extends HMultiMap {
class Mapping[K, V]
object Mapping {
implicit object k extends Mapping[KEY_EVENT.type, KeyEventObject => Unit]
implicit object m extends Mapping[MOUSE_EVENT.type, MouseEventObject => Unit]
}
}
少し面倒ですが、使い方はもっときれいです。
val eventListeners = new EventMap
eventListeners.add(KEY_EVENT)((e: KeyEventObject) => println(e.c))
eventListeners.add(MOUSE_EVENT)((e: MouseEventObject) => println("X: " + e.x))
eventListeners.add(KEY_EVENT)((e: KeyEventObject) => println(e.c + " again"))
個々の種類のイベントハンドラーを選択できることを確認できます。
scala> eventListeners(KEY_EVENT).size
res3: Int = 2
そして、イベントを発生させて、そのすべてのハンドラーを実行するふりをすることができます。
scala> eventListeners(KEY_EVENT).foreach(_(KeyEventObject('a')))
a
a again
そして、適切な証拠がなければ、下にある緩く型付けされたマップには何も入らないので、すべて完全に安全です。たとえば、からString
に関数を追加しようとすると、コンパイル時エラーが発生します。Unit