1

Child1在此示例中,我有一个创建子类型演员的演员。Child1构造函数采用两个StringSomeTrait ,它们是从混合到实例中的变量中提取的SomeActor

trait SuperTrait {
  lazy val str1: Option[String] = None
  lazy val str2: Option[String] = None
} 
trait SomeTrait extends SuperTrait {
  override lazy val str1: Option[String] = Some("Str1")
  override lazy val str2: Option[String] = Some("Str2")
}
class SomeActor extends Actor {
  this: SuperTrait => 
  var child: Option[ActorRef] = None
  override def preStart(): Unit = {
    child = for {
      st1 <- str1 
      st2 <- str2
    } yield context.actorOf(Child1.props(st1, st2)))
  }
}

SomeActor实例上创建:

context.actorOf(Props[SomeActor with SomeTrait])

有了这个我得到奇怪的错误:

SomeActor cannot be cast to SomeTrait.

似乎从Option 容器中提取变量SomeTrait会引发该异常。

我在这里想念什么?

它不仅发生在for comprehensions 上。此外,当我尝试执行str1.getOrElse("")或添加吸气剂时SomeTraitdef getStr1 = str1.getOrElse("")

4

1 回答 1

3

正如上面@ggovan 所说,使用 Akka 时,您无法控制 Actor 的构造。Akka 库负责处理这一点(这就是您使用 Props 封装传递给构造函数的参数的原因)。这样做的原因是,如果你的 actor 崩溃了,它的主管需要能够创建它的一个新实例。

当您使用 Props[X] 时,Scala 使用 aaClassTag来查找 Actor 的运行时类。但是,ClassTag似乎没有拾取您调用时创建的匿名类Props[X with Y],它只拾取基类(在您的情况下,SomeActor)。一种解决方法是使用 Props 的别名选项,因此您可以在创建 SomeActor 时执行此操作:

val actor = sys.actorOf(Props(new SomeActor with SomeTrait))

这行得通,它也拾取了被覆盖的惰性 val。但是,请务必阅读http://doc.akka.io/docs/akka/snapshot/scala/actors.html(“危险变体”部分)中的缺点。

另一种选择是使用蛋糕模式:

trait SomeTrait {
  lazy val str1: Option[String] = None
  lazy val str2: Option[String] = None
}

trait ActorTrait extends Actor {
  this: SomeTrait => 
  override lazy val str1 = Some("Str1")
  override lazy val str2 = Some("Str2")
  var child: Option[ActorRef] = None
  override def preStart(): Unit = {
    child = for {
      st1 <- str1 
      st2 <- str2
    } yield context.actorOf(Child1.props(st1, st2)))
  }
}

class SomeActor extends ActorTrait with SomeTrait

在这种情况下,您可以使用推荐的Props[SomeActor]方法来创建 Props 对象。

于 2014-06-30T17:55:15.850 回答