Groovy - fechamentos

Um encerramento é um pequeno bloco anônimo de código. Normalmente abrange apenas algumas linhas de código. Um método pode até mesmo tomar o bloco de código como parâmetro. Eles são anônimos por natureza.

A seguir está um exemplo de um fechamento simples e sua aparência.

class Example {
   static void main(String[] args) {
      def clos = {println "Hello World"};
      clos.call();
   } 
}

No exemplo acima, a linha de código - {println "Hello World"} é conhecida como encerramento. O bloco de código referenciado por este identificador pode ser executado com a instrução de chamada.

Quando executamos o programa acima, obteremos o seguinte resultado -

Hello World

Parâmetros formais em fechamentos

Os fechamentos também podem conter parâmetros formais para torná-los mais úteis, assim como os métodos do Groovy.

class Example {
   static void main(String[] args) {
      def clos = {param->println "Hello ${param}"};
      clos.call("World");
   } 
}

No exemplo de código acima, observe o uso de $ {param} que faz com que o fechamento receba um parâmetro. Ao chamar o fechamento por meio da instrução clos.call, agora temos a opção de passar um parâmetro para o fechamento.

Quando executamos o programa acima, obteremos o seguinte resultado -

Hello World

A próxima ilustração repete o exemplo anterior e produz o mesmo resultado, mas mostra que um único parâmetro implícito referido como pode ser usado. Aqui, 'it' é uma palavra-chave no Groovy.

class Example {
   static void main(String[] args) {
      def clos = {println "Hello ${it}"};
      clos.call("World");
   } 
}

Quando executamos o programa acima, obteremos o seguinte resultado -

Hello World

Fechamentos e Variáveis

Mais formalmente, os fechamentos podem se referir a variáveis ​​no momento em que o fechamento é definido. A seguir está um exemplo de como isso pode ser alcançado.

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");
   } 
}

No exemplo acima, além de passar um parâmetro para o encerramento, também estamos definindo uma variável chamada str1. O fechamento também assume a variável junto com o parâmetro.

Quando executamos o programa acima, obteremos o seguinte resultado -

Hello World 
Welcome World

Usando fechamentos em métodos

Os fechamentos também podem ser usados ​​como parâmetros para métodos. No Groovy, muitos dos métodos embutidos para tipos de dados, como listas e coleções, têm fechamentos como um tipo de parâmetro.

O exemplo a seguir mostra como um encerramento pode ser enviado a um método como um parâmetro.

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);
   } 
}

No exemplo acima,

  • Estamos definindo um método estático chamado Display, que tem um encerramento como argumento.

  • Em seguida, estamos definindo um encerramento em nosso método principal e passando-o para o nosso método Display como um parâmetro.

Quando executamos o programa acima, obteremos o seguinte resultado -

Hello World 
Welcome World 
Welcome Inner

Fechamentos em coleções e string

Vários métodos List, Map e String aceitam um encerramento como argumento. Vejamos um exemplo de como os fechamentos podem ser usados ​​nesses tipos de dados.

Usando fechamentos com listas

O exemplo a seguir mostra como os fechamentos podem ser usados ​​com Listas. No exemplo a seguir, estamos primeiro definindo uma lista simples de valores. O tipo de coleção de lista então define uma função chamada.each. Esta função assume um fechamento como parâmetro e aplica o fechamento a cada elemento da lista.

class Example {
   static void main(String[] args) {
      def lst = [11, 12, 13, 14];
      lst.each {println it}
   } 
}

Quando executamos o programa acima, obteremos o seguinte resultado -

11 
12 
13 
14

Usando fechamentos com mapas

O exemplo a seguir mostra como as interdições podem ser usadas com o Maps. No exemplo a seguir, estamos primeiro definindo um mapa simples de itens de valor-chave. O tipo de coleção de mapas então define uma função chamada .each. Esta função assume um fechamento como parâmetro e aplica o fechamento a cada par de valores-chave do mapa.

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}"}
   } 
}

Quando executamos o programa acima, obteremos o seguinte resultado -

TopicName = Maps 
TopicDescription = Methods in Maps 
TopicName maps to: Maps 
TopicDescription maps to: Methods in Maps

Freqüentemente, podemos desejar iterar entre os membros de uma coleção e aplicar alguma lógica apenas quando o elemento atender a algum critério. Isso é prontamente tratado com uma declaração condicional no encerramento.

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}
   } 
}

O exemplo acima mostra a expressão condicional if (num% 2 == 0) sendo usada no encerramento, que é usada para verificar se cada item na lista é divisível por 2.

Quando executamos o programa acima, obteremos o seguinte resultado -

1 
2 
3 
4 
The list will only display those numbers which are divisible by 2.
2 
4

Métodos usados ​​com fechamentos

Os próprios fechos fornecem alguns métodos.

Sr. Não. Métodos e Descrição
1 encontrar()

O método find encontra o primeiro valor em uma coleção que corresponde a algum critério.

2 encontrar tudo()

Ele encontra todos os valores no objeto receptor que correspondem à condição de fechamento.

3 qualquer () e cada ()

O método any itera por meio de cada elemento de uma coleção, verificando se um predicado booleano é válido para pelo menos um elemento.

4 coletar ()

O método collect itera por meio de uma coleção, convertendo cada elemento em um novo valor usando o fechamento como o transformador.