Когда на свойство ссылаются в замыкании, и эта ссылка не может быть разрешена в замыкании, предпринимаются попытки разрешить его в различных «местах»
this
- Свойство замыкания
delegate
, которое можно переназначить
- Закрытие
owner
В вашем примере var1
и var2
являются примерами ссылок, которые не могут быть разрешены в закрытии.
Следующее присваивает делегату замыкания config
и гарантирует, что это первое «место», которое будет использоваться для разрешения неразрешенных ссылок
def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config
Поэтому, когда мы устанавливаем свойства var1
и var2
в замыкании, они разрешаются в config
, т. Е. Устанавливаются как пары ключ-значение этой Map
.
Если ваш пример был изменен на:
foo {
def var3 = "some value"
var1 = "foo value 1"
var2 = "foo value 2"
var3 = "some value"
}
var3
будет не разрешаться config
, потому что оно может быть разрешено в закрытии.
Обновление
В ответ на ваш комментарий, который (я думаю) спрашивает: почему установка делегата замыкания на карту вызывает добавление пары ключ-значение к этой карте?
Когда var1 = "foo value 1"
не может быть разрешено в закрытии, вместо этого оно разрешается против карты, из-за этого
def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config
так что это фактически означает, что мы звоним
config.var1 = "foo value 1"
, что является сокращенным сокращением для
config.put("var1", "foo value 1")
Может быть, немного легче понять, если вы измените свой код для непосредственного вызова метода put
, например,
def foo = {
put('var1', "foo value 1")
}
def call(body) {
def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config
body()
println config.var1 // display foo value 1 : for me the magic is here !!
}
call(foo)
Если вы запустите этот код в Groovy Console, вы увидите, что он также печатает «foo value 1».
Если вы все еще боретесь, возможно, этот вопрос поможет.