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