绑定和闭包 Groovy

5

我不知道如何在Groovy中使用闭包绑定。我编写了一个测试代码,但在运行时它显示“缺少传递为参数的闭包上的setBinding方法”。

void testMeasurement() {
    prepareData(someClosure)
}
def someClosure = {
  assertEquals("apple", a)
}


  void prepareData(testCase) {
    def binding = new Binding()
    binding.setVariable("a", "apple")
    testCase.setBinding(binding)
    testCase.call()

  }
2个回答

6

这对我来说在Groovy 1.7.3中有效:

someClosure = {
  assert "apple" == a
}
void testMeasurement() {
  prepareData(someClosure)
}
void prepareData(testCase) {
  def binding = new Binding()
  binding.setVariable("a", "apple")
  testCase.setBinding(binding)
  testCase.call()
}
testMeasurement()

在这个脚本示例中,setBinding调用将a设置为脚本绑定(正如您可以从Closure文档链接中看到,没有setBinding调用)。因此,在setBinding调用之后,您可以调用。
println a

并且它会打印出"apple"

那么在类中,您可以设置闭包的代理(当本地找不到属性时,闭包将恢复到此代理):

class TestClass {
  void testMeasurement() {
    prepareData(someClosure)
  }

  def someClosure = { ->
    assert "apple" == a
  }

  void prepareData( testCase ) {
    def binding = new Binding()
    binding.setVariable("a", "apple")
    testCase.delegate = binding
    testCase.call()
  }
}

它应该从委托类(在此情况下是绑定)中获取a的值。

这个页面介绍了闭包中委托和变量作用域的用法。

事实上,您可以使用一个简单的Map来代替使用Binding对象,如下所示:

  void prepareData( testCase ) {
    testCase.delegate = [ a:'apple' ]
    testCase.call()
  }

希望有所帮助!

0

这真是一种奇怪的行为:在 someClosure 声明前删除“def”可以使脚本在 JDK1.6 Groovy:1.7.3 中正常工作。

更新:这在上面的答案中已经提到了。我重复了一遍是我的错误。 更新:为什么它能工作?没有 def,第一行被视为属性赋值,调用 setProperty 并在绑定中使变量可用,稍后将其解析。 根据 (http://docs.codehaus.org/display/GROOVY/Groovy+Beans),一个 def 也应该像这样工作。

someClosure = {
    assert "apple", a
    print "Done"
}

void testMeasurement() {
    prepareData(someClosure)
}

void prepareData(testCase) {
    def binding = new Binding()
    binding.setVariable("a", "apple")
    testCase.setBinding(binding)
    testCase.call()
}
testMeasurement()

我可以通过以下代码重现您提到的问题。但我不确定这是否是使用Binding的正确方式。GroovyDocs说它们应该与脚本一起使用。您能否指向建议在闭包中使用Binding的文档。

class TestBinding extends GroovyTestCase {
    void testMeasurement() {
        prepareData(someClosure)
    }

    def someClosure = {
        assertEquals("apple", a)
    }

    void prepareData(testCase) {
        def binding = new Binding()
        binding.setVariable("a", "apple")
        //this.setBinding(binding)
        testCase.setBinding(binding)
        testCase.call()
    }
}

这个问题在Groovy邮件列表上得到了解答:

在脚本中,def foo将创建一个局部变量,而不是属性(私有字段+getter/setter)。 可以把脚本想象成run()或main()方法的主体。 这就是您定义局部变量的位置和方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接