我对Scala泛型中的界限如何工作感到困惑。请考虑以下事项:
sealed trait MessageBody
case class Body1() extends MessageBody
case class Body2() extends MessageBody
sealed trait MessageKey[T <: MessageBody]
case object Key1 extends MessageKey[Body1]
case object Key2 extends MessageKey[Body2]
type MessageHandler[B <: MessageBody] = PartialFunction[MessageKey[B], B => Unit]
abstract class Handler {
def messageHandler[B <: MessageBody]: MessageHandler[B]
}
class ProcessingHandler[ReturnType <: MessageBody](val onSuccess: MessageKey[ReturnType]) extends Handler {
override def messageHandler[B <: MessageBody]: MessageHandler[B] = {
case `onSuccess` => success
}
def success(msg: ReturnType): Unit = println(msg)
}
这给了我一个错误:
error: type mismatch;
found : ReturnType => Unit
required: B => Unit
case `onSuccess` => success
^
在我天真的理解中,ReturnType
和B
都是MessageBody
的子类型,因此必须兼容。那么为什么它们不兼容,我应该如何编写代码以使它们兼容呢?
编辑:下面的一段代码工作正常,如果我在任何地方混合MessageKey
和MessageBody
实例之间的关系,我会得到一个很好的编译时错误。
class ProcessingHandler2 extends Handler {
override def messageHandler[B <: MessageBody]: MessageHandler[B] = {
case Key1 => h1
// case Key1 => h2 // gives compile-time error
case Key2 => h2
}
def h1(x: Body1): Unit = println(x)
def h2(x: Body2): Unit = println(x)
}
val handler: Handler = new ProcessingHandler2
handler.messageHandler(Key1)(Body1())
// handler.messageHandler(Key1)(Body2()) // gives compile-time error
编辑:显然,没有办法编译检查:handler.messageHandler(Key3)
这将在运行时产生MatchError
。
答案 0 :(得分:2)
假设您有ProcessingHandler[Body1]
类型的对象,然后在其上调用messageHandler[Body2]
。根据签名,它应返回Body2 => Unit
,但您尝试返回Body1 => Unit
。如果您尝试返回MessageBody => Unit
,那就没问题,因为MessageBody
是Body2
的超类,但Body1
不是。Body2
。它们都是同一个超类的子类,但这并不能使它们兼容,也就是说你不能将Body1
作为参数传递给一个带Handler
的函数,反之亦然。
根据您的要求,您可以做多件事:
您可以messageHandler
通用而不是Handler[ReturnType]
,然后扩展Handler
(或者您可以为messageHandler
提供成员类型并在success
中使用它
或者您可以MessageBody
取ReturnType
作为参数,而不是-Dosgi.requiredJavaVersion=1.7
。