
|
1
2
|
def closure = { println "I am a closure" }closure() // Prints I am a closure |
Итак, первое, что нужно сказать, это то, что закрытие не печатается, когда закрытие определено, а только когда оно вызывается Закрытия облегчают отложенное выполнение. Также возможно передать параметры в замыкание
|
1
2
|
def closureWithParameters = {x, y -> print(x + " and " + y)}closureWithParameters("Hello dudes", "Hello Mega Dude") // Prints Hello dudes and Hello Mega Dude |
Когда замыкание имеет только один параметр, нам даже не нужен ->, мы можем просто использовать неявную переменную it .
|
1
2
|
def closureWithParameters = { println it }closureWithParameter("Hello dude") // Prints Hello dude |
Сейчас, сейчас, сейчас детишки. Замыкания существуют не только в Groovy, они существуют во многих языках, и одна из их особенностей, о которых люди иногда забывают, состоит в том, что они содержат представление лексической среды функции. В английском это означает, что они получают снимок контекста, в котором они определены, и только они могут получить доступ к этому снимку и изменить его. В JavaScript мы можем сделать что-то вроде этого:
|
1
2
3
4
5
6
7
|
function outerFuntion () { var counter = 1; function innerFunction() { alert("Counter=" + counter++); } return innerFunction;} |
Несмотря на то, что счетчик определен в externalFunction () как локальная переменная, он считается находящимся в лексической среде innerFunction (), поэтому он может получить к нему доступ. Когда innerFunction () возвращается в качестве замыкания, он получает свое собственное значение, к которому имеет доступ только он. Так что, если мы должны были сделать это:
|
1
2
|
var myClosure = outerFuntion(); // myFunc is now a pointer to the innerFunction closure.myClosure(); // Executes Counter=1; |
Сначала выполняется externalFunction (), и он возвращает замыкание innerFunction. Переменная присваивается этому закрытию. Теперь, сейчас, сейчас, обратите внимание, что ключевое слово здесь «вернулся». innerFunction () возвращается , он не выполняется. Итак, снова мы видим задержку исполнения, характерную для замыканий. Каждый раз, когда мы выполняем замыкание, счетчик увеличивается.
|
1
2
3
4
5
|
myClosure(); // Executes Counter=2;myClosure(); // Executes Counter=3;myClosure(); // Executes Counter=4;myClosure(); // Executes Counter=5;myClosure(); // Executes Counter=6; |
Таким образом, закрытие имеет состояние, которое оно запоминает через вызовы. Это состояние начинается как моментальный снимок контекста, в котором определена функция, и это то, что могут изменить только их закрытие. Так что да, это ключевой момент закрытия. Это особый вид объекта, который объединяет две вещи: функцию и среду, в которой эта функция была создана. Среда состоит из переменных, которые находились в области действия во время создания замыкания. Итак, вернемся к Groovy. Тот же пример будет выглядеть так:
|
1
2
3
4
5
6
|
def outerFunction () { def counter = 1; return { print "Counter=" + counter++ }} |
|
1
2
3
4
5
6
7
8
|
def myClosure = outerFunction()myClosure(); // executes 1 myClosure(); // executes 2myClosure(); // executes 3 myClosure(); // executes 4myClosure(); // executes 5 myClosure(); // executes 6 |
Это очень похоже на пример JavaScript. Слово def используется вместо функции . Мы также просто используем тот факт, что вам не нужно использовать функцию слова в Groovy, когда вы хотите определить анонимную функцию. Если бы мы хотели сделать внутреннюю функцию анонимной в версии JavaScript, мы могли бы сделать:
|
01
02
03
04
05
06
07
08
09
10
|
function outerFuntion () { var counter = 1; return function () { alert("Counter=" + counter++); };}var myClosure = outerFuntion(); // myFunc is now a pointer to the innerFunction closure.myClosure(); // Executes Counter=1;myClosure(); // Executes Counter=2; |
Но все равно придется использовать слово function, нам просто не нужно давать ему имя. Хорошо, так что до следующего раза береги себя.