2009-09-08 16 views
6

Mi comprensión del operador de Groovy .& es que convierte una llamada a método en un cierre. Por lo tanto parece que el siguiente código (que se puede ejecutar en el Groovy console) debería funcionar:Método de invocación como cierre

class Foo { 
    def method(def param) { 
    param + 10 
    } 
} 

def invokeClosure = {Closure closure -> 
    return closure.call() 
} 

def f = new Foo() 
invokeClosure f.&method(6) 

Por supuesto, si cambio de la última línea de

invokeClosure {f.method(6)} 

que trabaja muy bien, pero ¿qué hay de malo mi comprensión del operador .&?

Gracias, Don

Respuesta

8

Al convertir un método para un cierre usando . & notación que deja fuera de los parámetros. F. & método (6) es lo mismo que llamar a f.method (6) que devolverá 16, por lo que en su ejemplo está pasando 16 a invokeClosure y no a un cierre. Lo que provoca la siguiente excepción ya que la clase de enteros no tiene un método llamado:

excepción lanzada: No hay ninguna firma de método: java.lang.Integer.call()

A continuación pasa un puntero método para f.method en invokeClosure y sería la forma en que normalmente usaría. &.

class Foo { 
    def method(def param) { 
    param + 10 
    } 
} 

def invokeClosure = {Closure closure -> 
    return closure.call(6) // can leave off .call 
} 

def f = new Foo() 
invokeClosure f.&method 

Como usted ha señalado el siguiente trabajo:

invokeClosure {f.method(6)} 

Eso es porque usted está pasando un cierre que no toma parámetros y por eso closure.call() funciona en ese caso.

+1

En realidad, estrictamente hablando pienso '{f.method (6)}' es un cierre que toma un parámetro mientras que '{-> f.method (6)}' es un cierre que no toma params. ¡Gran respuesta, gracias! –

1

Use invokeClosure f.&method.curry(6) en su lugar. Este es un cierre que podría llamarse sin los parámetros

0

El ejemplo anterior también podría ampliarse para tomar el parámetro como argumento en el invokeClosure. Eso le daría el resultado esperado y la sintaxis.

class Foo { 
    def method(def param) { 
    param + 10 
    } 
} 

def invokeClosure = {Closure closure, def parameter -> 
    return closure.call(parameter) 
} 

def f = new Foo() 
invokeClosure f.&method, 6 
Cuestiones relacionadas