在 Groovy 中将方法作为参数传递

Pass method as parameter in Groovy

提问人:David Moles 提问时间:3/6/2013 更新时间:11/7/2023 访问量:34281

问:

有没有办法在Groovy中将方法作为参数传递,而无需将其包装在闭包中?它似乎适用于函数,但不适用于方法。例如,鉴于以下情况:

def foo(Closure c) {
    c(arg1: "baz", arg2:"qux")
}

def bar(Map args) {
    println('arg1: ' + args['arg1'])
    println('arg2: ' + args['arg2'])
}

这工作原理:

foo(bar)

但是,如果是类中的方法:bar

class Quux { 
    def foo(Closure c) {
        c(arg1: "baz", arg2:"qux")
    }

    def bar(Map args) {
        println('arg1: ' + args['arg1'])
        println('arg2: ' + args['arg2'])
    }

    def quuux() { 
      foo(bar)
    }
} 

new Quux().quuux()

它失败,没有这样的属性:类:Quux 的栏

如果我将方法更改为包装在闭包中,它会起作用,但似乎不必要地冗长:bar

    def quuux() { 
      foo({ args -> bar(args) })
    }

有没有更清洁的方法?

Groovy 函数式编程 闭包

评论


答:

75赞 epidemian 3/6/2013 #1

.&操作员来救援!

class Quux { 
    def foo(Closure c) {
        c(arg1: "baz", arg2:"qux")
    }

    def bar(Map args) {
        println('arg1: ' + args['arg1'])
        println('arg2: ' + args['arg2'])
    }

    def quuux() { 
      foo(this.&bar)
    }
} 

new Quux().quuux()
// arg1: baz
// arg2: qux

通常,将返回一个绑定的方法,即调用 .obj.&methodmethodobj

3赞 Maicon Mauricio 8/13/2022 #2

除了方法指针运算符 () 之外,对于 Groovy 3.0.0 及更高版本,还有等效的、兼容的、众所周知的 Java 8+ 方法引用运算符 ()。.&::

def foo(Closure c) {
    c(func: "foo")
}

def bar(Map args = [:]) {
    println "$args.func bar"
}

println foo(this::bar)

输出:

foo bar

方法引用运算符,如 Groovy 的文档中所述:

[...]与 Groovy 提供的功能有些重叠 方法指针运算符。事实上,对于动态 Groovy,该方法 引用运算符只是方法指针运算符的别名。 对于静态 Groovy,运算符生成的字节码类似于 Java 将为相同的上下文生成的字节码。

0赞 Wendel 11/7/2023 #3

我使用 Groovy 2.3.7 创建了一个单元测试:

import junit.framework.TestCase

class ClosureTest extends TestCase {

    String foo(Closure c) {
        return c(func: "foo")
    }

    String bar(Map args = [:]) {
        return "$args.func bar"
    }

    void testFunctionCall() {
        assertEquals("foo bar", foo(this.&bar))
    }

}