"关闭封闭范围/类"是什么意思?

Pet*_*ter 15 closures akka

Akka文档记录了使用的危险变体Props:

// NOT RECOMMENDED within another actor:
// encourages to close over enclosing class
val props7 = Props(new MyActor)
Run Code Online (Sandbox Code Playgroud)

然后继续说明:

不推荐使用这种方法,因为它鼓励以关闭在所述封闭的范围,导致不可序列道具和可能的竞争条件(断裂演员封装)被另一个演员内使用.

有人可以解释一下"关闭封闭范围"的含义吗?一直在寻找,一无所获.谢谢.

agi*_*eel 19

在这个例子中看到,它new Actor被传递为一个所谓的"按名称"参数,这有点棘手.把它想象成它变成了类型的函数 () => Actor.每次重启时由其主管(重新)创建actor,都会调用此函数.

问题是这个函数是一个"闭包"(很容易谷歌;)),这意味着它捕获并记住它所需的周围范围内的所有东西(有时,但很少被称为"堆栈翻录").例如val f = (a: Int) => a + x.它x来自哪里?它来自周围的范围.分配给的函数litetal f称为"开放术语".在运行时,函数文字成为一个函数值(这是一种说"对象"的奇特方式),执行时会关闭开放项,同时捕获周围范围内的所有内容.这就是"封闭"这个名字的来源.

闭包是非常有用的,但你必须小心你关闭.有时x是一个def或上帝禁止a var,这导致不可预测的结果f,因为你无法控制f将被调用/执行的时间.试试看!

阿卡的两个非常常见的反模式是:

  1. this从内部类创建Actor时关闭(外部)引用.
  2. def sender在回复带有未来的消息时关闭.

我故意向谷歌提供了许多花哨的条款,顺便说一下;)

干杯和快乐的编码

  • 谢谢.丰富的解释. (2认同)

Eri*_*ner 8

作为@ agilesteel的正确答案的补充,一些参考:

解释什么是闭包:Scala编程,8.7,闭包

解释闭包可能导致序列化问题的原因:SIP-21 - 孢子

这是一个代码示例,根据SIP-21中的示例,创建一个不可序列化的Props对象,因为关闭了一个不可序列化的对象:

case class Helper(name: String)

object MyNonserializableObject {

    val helper = Helper("the helper")

    val props7 = Props(new MyActor(helper))
}
Run Code Online (Sandbox Code Playgroud)

即使它helper本身是可序列化的,"新的MyActor(帮助器)"也是按名称传递的,因此捕获this.helper,并且this不可序列化.

您可以看到actor参数是通过名称从Props apply方法的签名传递的,其中creator参数中有⇒ :

def apply[T <: Actor](creator: ? T)(implicit arg0: ClassTag[T]): Props
Run Code Online (Sandbox Code Playgroud)