Закрытие — это короткий анонимный блок кода. Обычно он занимает несколько строк кода. Метод может даже принять блок кода в качестве параметра. Они анонимны по своей природе.
Ниже приведен пример простого замыкания и как оно выглядит.
class Example { static void main(String[] args) { def clos = {println "Hello World"}; clos.call(); } }
В приведенном выше примере строка кода — {println «Hello World»} называется замыканием. Блок кода, на который ссылается этот идентификатор, может быть выполнен с помощью оператора вызова.
Когда мы запустим вышеуказанную программу, мы получим следующий результат —
Hello World
Формальные параметры в замыканиях
Замыкания также могут содержать формальные параметры, чтобы сделать их более полезными, как и методы в Groovy.
class Example { static void main(String[] args) { def clos = {param->println "Hello ${param}"}; clos.call("World"); } }
В приведенном выше примере кода обратите внимание на использование $ {param}, который заставляет замыкание принимать параметр. При вызове замыкания с помощью оператора clos.call у нас теперь есть возможность передать параметр в замыкание.
Когда мы запустим вышеуказанную программу, мы получим следующий результат —
Hello World
Следующая иллюстрация повторяет предыдущий пример и дает тот же результат, но показывает, что может использоваться неявный единственный параметр, упоминаемый как он. Здесь «это» является ключевым словом в Groovy.
class Example { static void main(String[] args) { def clos = {println "Hello ${it}"}; clos.call("World"); } }
Когда мы запустим вышеуказанную программу, мы получим следующий результат —
Hello World
Замыкания и Переменные
Более формально, замыкания могут ссылаться на переменные во время определения замыкания. Ниже приведен пример того, как этого можно достичь.
class Example { static void main(String[] args) { def str1 = "Hello"; def clos = {param -> println "${str1} ${param}"} clos.call("World"); // We are now changing the value of the String str1 which is referenced in the closure str1 = "Welcome"; clos.call("World"); } }
В приведенном выше примере, помимо передачи параметра в замыкание, мы также определяем переменную с именем str1. Закрытие также принимает переменную вместе с параметром.
Когда мы запустим вышеуказанную программу, мы получим следующий результат —
Hello World Welcome World
Использование замыканий в методах
Замыкания также могут быть использованы в качестве параметров методов. В Groovy многие встроенные методы для типов данных, таких как списки и коллекции, имеют в качестве типа параметра замыкания.
В следующем примере показано, как замыкание можно отправить методу в качестве параметра.
class Example { def static Display(clo) { // This time the $param parameter gets replaced by the string "Inner" clo.call("Inner"); } static void main(String[] args) { def str1 = "Hello"; def clos = { param -> println "${str1} ${param}" } clos.call("World"); // We are now changing the value of the String str1 which is referenced in the closure str1 = "Welcome"; clos.call("World"); // Passing our closure to a method Example.Display(clos); } }
В приведенном выше примере
-
Мы определяем статический метод с именем Display, который принимает замыкание в качестве аргумента.
-
Затем мы определяем замыкание в нашем основном методе и передаем его в наш метод Display в качестве параметра.
Мы определяем статический метод с именем Display, который принимает замыкание в качестве аргумента.
Затем мы определяем замыкание в нашем основном методе и передаем его в наш метод Display в качестве параметра.
Когда мы запустим вышеуказанную программу, мы получим следующий результат —
Hello World Welcome World Welcome Inner
Замыкания в коллекциях и строках
Несколько методов List, Map и String принимают в качестве аргумента замыкание. Давайте рассмотрим пример использования замыканий в этих типах данных.
Использование замыканий со списками
В следующем примере показано, как замыкания можно использовать со списками. В следующем примере мы сначала определяем простой список значений. Тип коллекции списка затем определяет вызываемую функцию. каждый Эта функция принимает замыкание в качестве параметра и применяет замыкание к каждому элементу списка.
class Example { static void main(String[] args) { def lst = [11, 12, 13, 14]; lst.each {println it} } }
Когда мы запустим вышеуказанную программу, мы получим следующий результат —
11 12 13 14
Использование замыканий с картами
В следующем примере показано, как замыкания можно использовать с Картами. В следующем примере мы сначала определяем простую карту элементов значения ключа. Тип коллекции карт затем определяет функцию с именем .each. Эта функция принимает замыкание в качестве параметра и применяет замыкание к каждой паре ключ-значение на карте.
class Example { static void main(String[] args) { def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"] mp.each {println it} mp.each {println "${it.key} maps to: ${it.value}"} } }
Когда мы запустим вышеуказанную программу, мы получим следующий результат —
TopicName = Maps TopicDescription = Methods in Maps TopicName maps to: Maps TopicDescription maps to: Methods in Maps
Часто нам может потребоваться перебрать членов коллекции и применить некоторую логику только в том случае, если элемент удовлетворяет некоторому критерию. Это легко обрабатывается условным оператором в замыкании.
class Example { static void main(String[] args) { def lst = [1,2,3,4]; lst.each {println it} println("The list will only display those numbers which are divisible by 2") lst.each{num -> if(num % 2 == 0) println num} } }
Вышеприведенный пример показывает условное выражение if (num% 2 == 0), используемое в замыкании, которое используется для проверки, делится ли каждый элемент в списке на 2.
Когда мы запустим вышеуказанную программу, мы получим следующий результат —
1 2 3 4 The list will only display those numbers which are divisible by 2. 2 4
Методы, используемые с замыканиями
Сами замыкания предоставляют некоторые методы.
Метод find находит первое значение в коллекции, которое соответствует некоторому критерию.
Он находит все значения в принимающем объекте, соответствующие условию закрытия.
Метод any перебирает каждый элемент коллекции, проверяя, является ли логический предикат действительным хотя бы для одного элемента.
Метод collect перебирает коллекцию, преобразуя каждый элемент в новое значение, используя замыкание в качестве преобразователя.