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)
}