【问题标题】:call methods on akka actors in scala在 scala 中调用 akka 演员的方法
【发布时间】:2012-11-08 14:50:46
【问题描述】:

我有一个这样定义的演员:

class nodeActor(ID: String) extends Actor

其中包含一个方法,用于在启动actor之前对其进行设置:

def addRef(actor:ActorRef)

我这样实例化这个actor:

val node1 = system.actorOf(Props(new nodeActor("node1")), name="node1")

返回一个 ActorRef。编译器不允许我在 ActorRef 上调用“addRef”,因为它是子类型的成员。所以我使用以下方法投射节点:

node1.asInstanceOf[nodeActor].addRef(link1)

这让编译器很高兴。然后在运行时我得到

java.lang.ClassCastException: akka.actor.LocalActorRef cannot be cast to ActorStressTest.nodeActor

这对我来说似乎没有意义,因为它是一个子类型,我应该能够转换为它。

想法?

【问题讨论】:

  • 请通过发送消息而不是直接方法调用与actor通信。那些实现 Actor 的人努力将真实的 Actor 实例隐藏在 ActorReferences 后面。这是一种不同的编程模型。习惯就好。
  • 一般来说“它是一个子类型..我应该能够转换成它”是一个危险的断言。当且仅当所指对象符合该子类型时,您才可以转换对子类型的引用,这通常不是正确的,并且在您的情况下显然不是正确的。
  • 嗨@Alex,我衷心建议您在进一步冒险之前仔细阅读documentation。它可能会帮助您避免许多陷阱和许多无意义的工作。真诚的。
  • “它是一个子类型..我应该能够转换成它” - 这甚至不是真的:node1 是一个ActorRef,它的作用就像一个指向实际 Actor 实例的指针。您的 nodeActor 实例隐藏在 Akka 系统中,并不意味着直接与之交互。
  • @Dylan 好的,这似乎是我的问题所在。我认为一个 ActorRef,因为它是由构造函数类型返回的,所以它是实际的 actor 对象,而不仅仅是指向系统的指针。现在说得通了。

标签: scala akka actor


【解决方案1】:

如果你想这样做是为了测试,那么在创建演员时你可以这样做:

import akka.testkit.TestActorRef
val actorRef = TestActorRef[MyActor]
val actor = actorRef.underlyingActor

然后你可以在actor上运行方法

【讨论】:

  • 对我很有帮助的答案。 :) +1
【解决方案2】:

您不应该直接从另一个类调用演员的方法。它打破了系统的整体设计,即

  • 通过仅与调用actorOf或actorFor获得的ActorRef通信来封装actor的具体实现
  • 使用可用的(!、?)方法将参与者之间的通信限制为消息传递

如果您需要在 ActorA 中创建对另一个 ActorB 的引用,您可以:

如果您需要调用方法来满足接口/特征约束,请查看Typed Actors

【讨论】:

  • 感谢您的回答。我将重构我的代码以记住这一点。我知道您打算使用消息传递,但我不知道您正在使用方法调用来进行设置。无论如何,再次感谢,回答已接受。
【解决方案3】:

您可以将任何东西强制转换为任何东西,编译器会很乐意这样做,但如果不可能,运行时检查将失败。 ActorRef 不是您的 Actor 类的实例或其子类型。

当你这样做时:

system.actorOf(Props(new nodeActor("node1")), name="node1")

您会返回一个ActorRef,您应该只向其发送消息。除此之外,当您调用 system.actorOf 时,actor 会立即启动,因此无法在 Actor 实例启动之前尝试调用它的方法。

这里是来自Akka Docs 的演员的描述,解释了演员参考。

【讨论】:

    猜你喜欢
    • 2019-04-23
    • 2014-06-13
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 2018-05-23
    • 2016-03-07
    • 2016-01-24
    相关资源
    最近更新 更多