Scala 具有扩展类的泛型类型的函数

Scala 具有扩展类的泛型类型的函数,scala,Scala,我试图使用一个使用泛型类型的函数,该泛型类型作为映射定义的一部分传递 这是我的密码 object EventMapping { val eventMapping = collection.mutable.Map[Class[_ <: EventBase], (User, EventBase) => Unit]() setMapping(classOf[UserCreated], (user, evt) => user.loadUserName(evt.use

我试图使用一个使用泛型类型的函数,该泛型类型作为映射定义的一部分传递

这是我的密码

object EventMapping {


  val eventMapping =  collection.mutable.Map[Class[_ <: EventBase], (User, EventBase) => Unit]()

    setMapping(classOf[UserCreated], (user, evt) => user.loadUserName(evt.userName))


   private def setMapping[T <: EventBase](clazz: Class[T],fn: (User, T) => Unit) {
    eventMapping += clazz -> fn.asInstanceOf[(User, EventBase) => Unit]
  }

}

我预期EVT会被看作是创建用户事件,但编译器仍然认为EVETBASE.

基于Java的类似代码也可以工作,但我不知道这里缺少了什么

这里是UserCreated类

class UserCreated @JsonCreator() (@JsonProperty("userName")val userName: String) extends EventBase{


  @JsonProperty("userName") def getUserName: String = {
    userName
  }
}
这是堆栈跟踪

[info] Compiling 5 Scala sources to /Development/proyectX/target/scala-2.11/classes...
[error] /Development/proyectX/app/persistance/EventMapping.scala:11: missing parameter type
[error]   setMapping(classOf[UserCreated], (user, evt) => user.loadUserName(evt.asInstanceOf[UserCreated].userName))
[error]                                           ^
[error] one error found
[error] (compile:compile) Compilation failed

问题是在
setMapping
的定义中,您只告诉编译器
T
EventBase
的子类型。因此,当您调用
setMapping
并且在调用中有
evt.userName
时,编译器无法保证
EventBase
的所有子类型都支持
userName
成员,因此这是一个编译错误。因此,当您执行
evt.asInstanceOf[UserCreated].userName
时,您个人向编译器保证
evt
确实是
UserCreated
成员,并且它支持
userName
成员

其次,
缺少参数类型
编译错误(顺便说一句,不是堆栈跟踪,堆栈跟踪仅来自运行时异常)是Scala的类型推断算法不完善的结果。由于算法中的一个怪癖,您可以通过将映射函数(
fn
)移动到其自身的参数列表中,使其更精确:

object EventMapping {
  val eventMapping =
    collection.mutable.Map[Class[_ <: EventBase], (User, EventBase) => Unit]()

  setMapping(classOf[UserCreated]) { (user, evt) =>
    user.loadUserName(evt.userName)
  }

  private def setMapping[T <: EventBase](
    clazz: Class[T])(fn: (User, T) => Unit): Unit =
    eventMapping += clazz -> fn.asInstanceOf[(User, EventBase) => Unit]
}
这告诉编译器,无论您在哪里都有泛型类型
T
,在此调用中,将其替换为
UserCreated


另外,您必须向下转换的事实通常是一个迹象,表明您可能正在使用一种更为惯用和可组合的Scala功能—类型类。

错误是什么?您可以发布编译器错误消息吗?我添加了堆栈跟踪,这是我错过setMapping[UserCreated]的关键。非常感谢!
object EventMapping {
  val eventMapping =
    collection.mutable.Map[Class[_ <: EventBase], (User, EventBase) => Unit]()

  setMapping(classOf[UserCreated]) { (user, evt) =>
    user.loadUserName(evt.userName)
  }

  private def setMapping[T <: EventBase](
    clazz: Class[T])(fn: (User, T) => Unit): Unit =
    eventMapping += clazz -> fn.asInstanceOf[(User, EventBase) => Unit]
}
setMapping[UserCreated](classOf[UserCreated]) { (user, evt) =>
  user.loadUserName(evt.userName)
}