Closures

Um closure é um bloco de código ou um ponteiro para uma função. Todo closure, em Groovy, é uma instância de uma subclasse de Closure.

Execute o código a seguir usando o Groovy Web Console

Closure sum = {a, int b ->
   return a+b
}

println sum.getClass()
println sum.getClass().superclass
println sum(7, 9)
println sum(12.2, 3)
println sum('abc', 37)
// println sum('abc', 'def')

Os tipos são opcionais tanto na declaração da variável quanto dos parâmetros do closure:

def multiply = {a, b ->
   return a*b
}

println multiply.getClass()
println multiply.getClass().superclass
println multiply(7, 9)
println multiply(12.2, 3)
println multiply('abc', 5)
// println multiply('abc', 'def')

Se nenhum parâmetro for declarado explicitamente, o closure terá o parâmetro implícito “it”:

def p = {println it}
p('ok')

/* Parênteses opcionais. */
p 'ok'

Os parâmetros podem ter valores padrões

def add = {int a, b = 1 -> return a + b}
println(add 10, 5)
println(add(1))

O closure pode referenciar variáveis que não estão na lista de parâmetros dele. Essas variáveis são chamadas de variáveis livres (free variables):

def startTime = System.currentTimeMillis()
def printTime = {
    def time = System.currentTimeMillis() - startTime
    println "time = ${time} (ms)"
    startTime = System.currentTimeMillis()
}

Thread.sleep(2000)
printTime()
Thread.sleep(3000)
printTime()

Há três variáveis implícitas disponíveis para todo closure: this, owner e delegate.

class MyClass {

   def myClosure = {
       /* this = instância da classe na qual o closure foi definido. */
       println "this.class ${this.class}"

       def nestedClosure = {
           /* owner = this ou closure no qual o closure foi definido. */
           println "owner.class ${owner.class}"
       }
       nestedClosure()

       /* delegate = owner como padrão, mas pode ser alterado 
           para qualquer valor. */
       println "delegate.class ${delegate.class}"
   }

}

def closure = new MyClass().myClosure
closure.delegate = new Object()
closure()

Por ser um objeto, um closure pode ser usado como parâmetro para outros métodos ou closures:

class MyArrayList extends ArrayList {

    public void apply(Closure closure) {
        for (int i = 0; i < this.size(); i++) {
             this[i] = closure(this[i])
        }
    }

}

List list = [1, 2, 3, 4, 5, 6, 7, 8, 9] as MyArrayList

def p = {x -> print(x + ' '); return x}
list.apply(p)
println ''

def s = {x -> return x + 1}
list.apply(s)
println list

/* Closure como um bloco anônimo de código. */
list.apply({x -> return x - 1})
println list

/* Parênteses opcionais. */
list.apply{x -> return x - 1}
println list

Há uma sintaxe especial para quando o closure for o último parâmetro do método:

class MyArrayList extends ArrayList {

    public void apply(int times, Closure closure) {       
        for (i in (1..times)) {
           for (int j = 0; j < this.size(); j++) {
                 this[j] = closure(this[j])
            }
        }
    }

}

List list = [1, 2, 3, 4, 5, 6, 7, 8, 9] as MyArrayList

list.apply(3) {x -> return x + 1}
println list

É possível criar um novo closure com valores fixos para os parâmetros do closure original:

def add = {a, b -> return a + b}
def inc = add.curry(1)
println (add(7,3))
println (inc(7))

Referências adicionais

Deixe uma resposta

O seu endereço de email não será publicado Campos obrigatórios são marcados *

*


7 + = dezesseis

Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>