Подтвердить что ты не робот

Что означает "закрытие охватывающей области/класса"?

Документация Akka документирует опасные варианты использования Props:

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

Затем выполняется утверждение:

Этот метод не рекомендуется использовать в другом актере, потому что он призывает закрыть закрывающую область, в результате чего несериализуемые реквизиты и, возможно, расовые условия (нарушение инкапсуляция актера).

Может ли кто-нибудь объяснить смысл "закрытия закрывающей области"? Он все смотрел и ничего не нашел. Спасибо.

4b9b3361

Ответ 1

Немного сложно увидеть в этом примере, что new Actor передается в качестве так называемого параметра "по имени". Подумайте об этом, как будто он превращается в функцию типа () => Actor. Эта функция будет вызываться каждый раз, когда актер будет (повторно) создан его супервизором во время перезагрузки.

Проблема заключается в том, что эта функция является "закрытием" (очень просто для Google;)), что означает, что она захватывает и запоминает все в окружающем пространстве, которое ему нужно (иногда, но очень редко называемое "копирование стека" )). Например, val f = (a: Int) => a + x. Откуда берется x? Он исходит из окружающей сферы. Функция litetal, назначенная f, называется "открытым термином". Во время выполнения функция literal становится значением функции (это фантастический способ сказать "объект" ), который при выполнении закрывает открытый термин, захватывая все в окружающей области. То, откуда происходит название "закрытие".

Закрытие очень полезно, но вы должны быть осторожны, что вы закрываете. Иногда x является def или богом запрещает a var, что приводит к непредсказуемым результатам для f, потому что у вас нет контроля над временем, когда f будет вызываться/выполняться. Попробуйте!

Два очень распространенных антипатерна в Акке:

  • Закрытие (внешний) this справки при создании Актера из внутреннего класса.
  • Закрытие def sender при ответе на   сообщение с будущим.

Я дал вам кучу причудливых терминов для Google специально, btw;)

Приветствия и счастливое кодирование

Ответ 2

В качестве дополнения к отличному ответу @agilesteel некоторые ссылки:

Объясняет, какие замыкания: Программирование в Scala, 8.7, Закрытие

Объясняет, почему закрытие может вызвать проблемы сериализации: SIP-21 - Споры

И вот пример кода для создания объекта Props, который не является сериализуемым из-за закрытия над несериализуемым объектом на основе примера в SIP-21:

case class Helper(name: String)

object MyNonserializableObject {

    val helper = Helper("the helper")

    val props7 = Props(new MyActor(helper))
}

Даже если helper сам сериализуем, "новый MyActor (помощник)" передается по имени и поэтому захватывает this.helper, а this не является сериализуемым.

Вы можете видеть, что параметр actor передается по имени из подписи метода Props apply, где есть ⇒ в параметре creator:

def apply[T <: Actor](creator: ⇒ T)(implicit arg0: ClassTag[T]): Props