Код в закрытиях может относиться к it
переменная.
8.times { println it }
или
def mywith(Closure closure) {
closure()
}
mywith { println it }
С этим поведением в памяти Вы не можете ожидать, что следующий код распечатает 0011
2.times {
println it
mywith {
println it
}
}
И вместо этого я должен записать
2.times { i ->
println i
mywith {
println i
}
}
Мой вопрос: почему закрытия без переопределения параметров it
переменная, даже если им не нужен он.
Я думаю, это как-то связано с формальным определением замыкания Groovy:
замыкания могут иметь 1 ... N аргументов, которые могут быть статически типизированы или {{ 1}} нетипизированный. Первый параметр доступен через неявный нетипизированный аргумент с именем, если не указаны явные аргументы . Если вызывающий не указывает никаких аргументов, первый параметр (и, по расширению, it) будет нулевым.
Это означает, что замыкание Groovy всегда будет иметь по крайней мере один аргумент с именем it (если не указано иное) и it будет иметь значение null, если не задано в качестве параметра.
Во втором примере вместо этого используется объем охватывающего замыкания.
Если вы определите закрытие следующим образом
def closure = {println "i am a closure"}
Кажется, что у него нет параметров, но на самом деле у него есть один неявный параметр с именем it
. Это подтверждает:
def closure = {println "i am a closure with arg $it"}
closure("foo")
который выводит
"i am a closure with arg foo"
Если вы действительно хотите определить замыкание, принимающее 0 параметров, используйте следующее:
def closure = {-> println "i am a closure"}
Поэтому ваш пример можно переписать так:
2.times {
println it
mywith {->
println it
}
}