【问题标题】:Gradle/Groovy closure scope confusionGradle/Groovy 闭包范围混淆
【发布时间】:2015-11-29 11:39:05
【问题描述】:

我是 Gradle/Groovy 的新手,在嵌套闭包中遇到变量名称解析问题。我有一个自定义任务类,它定义了一些属性,并且我正在使用闭包实例化该类型的多个任务。这个闭包定义了一个与自定义任务类中的一个属性同名的变量,我遇到了一些奇怪的行为,这似乎违背了 Groovy 语言指南中定义的内容。有人可以回答下面代码中的问题吗?

class Something extends DefaultTask {
    def thing = "a"
}
/*
def thing = "b" // produces the error message:
                // > Could not find method b() for arguments [build_63hfhkn4xq8gcqdsf98mf9qak$_run_closure1@70805a56] on root project 'gradle-test'.
                // ...why?
*/
(1..1).each {
    def thing = "c"
    task ("someTask${it}", type: Something) {
        println resolveStrategy == Closure.DELEGATE_FIRST // prints "true"
        println delegate.class // prints "class Something_Decorated"
        println thing // prints "c" shouldn't this be "a" since it's using DELEGATE_FIRST?
        /*
        println owner.thing // produces the error message:
                            // > Could not find property 'thing' on root project 'gradle-test'
                            // shouldn't the "owner" of this closure be the enclosing closure?
                            // in that case shouldn't this resolve to "c"
        */
    }
}


编辑: 出于某种原因,在将所有 def 更改为 String 然后再改回 def 后,我无法再复制 def thing = "b" 行,从而产生奇怪的错误

【问题讨论】:

    标签: groovy gradle


    【解决方案1】:

    代码打印c,因为名为@9​​87654323@ 的变量是在闭包的词法范围内声明的。这意味着闭包可以只使用这个变量的值。什么会起作用:

    1. 重命名闭包中定义的thing变量。

    2. 通过delegate明确引用thing

      println delegate.thing

    【讨论】:

    • 所以如果它不能首先在闭包的词法范围内找到名称,它只会使用委托策略(在3.2.4 of the Groovy Language Guide部分提到)?
    • 据我了解,是的。
    • 好吧,这是有道理的。此外,在我将所有def 更改为String 然后又改回def 之后,我在def thing = "b" 行上遇到的那个奇怪错误似乎已经消失了(现在它只是产生一个错误,说@987654332 @ 已经在 def thing = "c" 行中定义了,这更有意义)...所以我将假设其中一个是一些奇怪的错误或其他东西。
    猜你喜欢
    • 2016-07-13
    • 1970-01-01
    • 2020-02-16
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 2020-06-13
    • 2020-05-21
    相关资源
    最近更新 更多