了解Scala中的方差

时间:2013-12-11 13:55:18

标签: scala generics akka

我有以下代码:

 trait DestinationBinding[T <: Actor] {
def resolve(implicit context: ActorContext, manifest: scala.reflect.ClassTag[T]): ActorRef = {
  println(s"creating destination binding actor of:$name")
  context.actorOf(Props[T], name)
}

def name: String = manifest.runtimeClass.getSimpleName
}

这基本上只是创建演员的一种简单方法。并遵循一些实施。

case class BlackHoleBinding extends DestinationBinding[BlackHoleDeliveryAgent]

BlackHoleDeliveryAgent是演员

还有一些消息:

case class Delivery[T <: Actor](message: Any, binding: DestinationBinding[T])

当我想模仿那些匹配时出现问题:

Note: com.elemica.erc.BlackHoleDeliveryAgent <: akka.actor.Actor (and BlackHoleBinding <:    DestinationBinding[BlackHoleDeliveryAgent]), but trait    DestinationBinding is invariant in type T.
[error] You may wish to define T as +T instead. (SLS 4.5)
[error]     case Delivery(message, binding: BlackHoleBinding) => {

1 个答案:

答案 0 :(得分:0)

方差总是有点棘手;这里的问题是你有BlackHoleDeliveryAgent是Actor的子类,但这并不意味着DestinationBinding [BlackHoleDeliveryAgent]是DestinationBinding [Actor]的子类,因此也不是任何其他DestinationBinding [T&lt;:Actor]的子类;这是因为DestinationBinding在T.上是不变的。

如果你在T中使用DestinationBinding协同变量,那么如果T是S的子类(在这种情况下你想要的话),它将意味着DestinationBinding [T]将是DestinationBinding [S]的子类。您可以通过定义DestinationBinding来执行此操作,如下所示:

trait DestinationBinding[+T <: Actor] {... }

为了便于知识,还有一个反变量注释将执行相反的操作,因此如果T是S DestiniationBinding [S]的子类,则它将是T的子类。这样做如下:< / p>

trait DestinationBinding[-T <: Actor] { ... }