从闭包访问局部变量



我正试图做一些类似的事情

def myFunc(Closure config) {
def var1
def var2
config()
println var1, var2
}
myFunc {
var1 = "hello"
var2 = "world"
}

有没有办法做到这一点?委托只适用于类字段,而不适用于本地变量。

Groovy脚本在读取给定属性的值时做一件事——当它存在于当前范围(局部变量、对象的字段等(中时,它使用它的值,否则它指的是binding对象,它持有所有不是变量、字段等的绑定。

在您的情况下会发生以下情况:

myFunc {
var1 = "hello"
var2 = "world"
}

当执行此闭包时,它将var1var2添加到具有相应值的binding中。执行myFunc时:

def myFunc(Closure config) {
def var1
def var2
config()
println var1
println var2
}

它不使用binding来读取var1var2的值,因为在当前范围内,这两个变量都存在,这就是的原因

null
null

打印。

但如果你把var1var2config()之后的阅读方式改成这样:

def myFunc(Closure config) {
def var1
def var2
config()
println binding.getVariable("var1") ?: var1
println binding.getVariable("var2") ?: var2
}

您将明确检查config()是否将var1var2添加到binding中,如果为true,您将读取由执行的闭包修改的值。否则,您将读取var1var2的本地默认值。

hello
world

这类似于从myFunc中删除局部变量并调用类似于的闭包

def myFunc(Closure config) {
config()
println var1
println var2
}

但在这种情况下,您仅指binding,在该过程中没有涉及局部变量的位置。我猜你必须处理现有的局部变量,而不能只是删除它们——在这种情况下,明确读取binding或局部变量是处理它的最佳方式

Gradle案例

如果在build.gradle脚本中遇到这种情况,您可以使用一种流行的方法来使用映射对象委托,因此闭包中使用的所有变量都会自动分配为映射属性。考虑以下示例:

def myFunc(Closure config) {
def var1
def var2
def map = [:]
config.delegate = map
config.resolveStrategy = Closure.DELEGATE_FIRST
config()
println map.getOrDefault('var1', var1)
println map.getOrDefault('var2', var2)
}
task hello {
doLast {
myFunc {
var1 = "hello"
var2 = "world"
}
}
}

在这种情况下,在给定闭包的情况下运行myFunc以在委托映射对象上分配var1var2属性结束。它为我们提供了使用map.getOrDefault(key,default)方法检索带有闭包的值集或使用默认局部变量值的机会。

您是否尝试删除如下所示的变量?

def myFunc(Closure config) {  
config()    
println var1
println var2
}
myFunc {   
var1 = "hello"   
var2 = "world" 
}

最新更新