【问题标题】:Referencing external val in actor class在actor类中引用外部val
【发布时间】:2014-10-12 14:31:27
【问题描述】:

这是设计禁止的还是我做错了什么?

val ext = 1

class Test extends Actor {
  def receive = { case _ => println(ext) }
}

try {
  val sys = ActorSystem("lol")
  sys.actorOf(Props[Test], "test") ! true
} catch {
  case e: Throwable => println(e)
}  

一旦我向Test 发送消息,我就会收到异常java.lang.IllegalArgumentException: no matching constructor found on class HelloAkkaScala$Test$1 for arguments []
如果我没有在 Test 类中引用 ext,我没有这个例外。
我正在使用 Akka 2.3.4

【问题讨论】:

  • 查看我的答案更新。

标签: scala closures akka


【解决方案1】:

访问在actor外部定义的val(不是var或任何其他可变状态)没有任何问题。

刚刚尝试在 Akka 2.3.5 中运行您的示例代码,它工作正常。您的原始代码中可能有错字。

更新

仔细查看您遇到的错误,您似乎已经在其他类中定义了 Test 类。

在这种情况下,inner class (Test) 将在幕后接收对 outer class 的引用,以便能够关闭其成员 (ext )。

这也意味着内部类的构造函数将引用外部类(语法糖隐藏了这一点)。

这也解释了您收到错误的原因(您将 0 个参数传递给构造函数,但实际上有一些隐藏的参数您没有提供)。

这里是重现这个的例子:

class Boot {

  val ext = 1

  class Test extends Actor {
    def receive = { case _ => println(ext) }
  }

  try {
    val sys = ActorSystem("lol")
    sys.actorOf(Props[Test], "test") ! true
  } catch {
    case e: Throwable => println(e)
  }

}

object Boot extends App {

  new Boot

}

... 这是一个快速的解决方法(在这种情况下,我通过将 Testext 移动到伴随对象来将它们设为“静态”,但是您可以通过将 ext 引用为其他一些实例,传递给构造函数):

class Boot {

  import Boot.Test

  try {
    val sys = ActorSystem("lol")
    sys.actorOf(Props[Test], "test") ! true
  } catch {
    case e: Throwable => println(e)
  }

}

object Boot extends App {

  val ext = 1

  class Test extends Actor {
    def receive = { case _ => println(ext) }
  }

  new Boot

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多