12

以下示例改编自“Groovy in Action”

class Mother {

    Closure birth() {                            
        def closure = { caller ->
            [this, caller]
        }
        return closure
    }
}                    

Mother julia = new Mother()
closure = julia.birth()                                
context = closure.call(this)                             

println context[0].class.name        // Will print the name of the Script class
assert context[1] instanceof Script 

根据书,this闭包内部的值是最外层范围(即julia声明的范围)。我是否正确地假设

  • this在闭包内部计算闭包被调用的范围?
  • 在上面显示的闭包内,thiscaller引用相同的范围?

谢谢,唐

4

4 回答 4

11

" this" 在 Groovy 中的块中总是意味着周围的类(实例)(无论是普通的类似 Java 的块还是闭包)。“ owner”是闭包的一个属性,指向嵌入对象,要么是一个类(实例),然后与“ this”相同,要么是另一个闭包。我会完全忘记这部分的范围。所以在上面的例子中,“这个”指的是一位母亲是正确的。

现在让事情变得复杂......“this”和隐含的 this 在 Groovy 中是不一样的。所以如果你有一个闭包{foo()}{this.foo()}你可以获得不同的结果。this.foo()将始终解析为嵌入类,而只会foo()使用 Groovy 元对象协议 (MOP) 解析,并且可以指向完全不同的东西。例如,对于标准的 Groovy 构建器,构建器可以在该闭包上设置一个委托并捕获方法调用。无论如何......这就是为什么这部分被称为动态范围。

历史背景:在 Groovy 1.0 之前,“this”是 Closure 对象本身。但是已更改,因为this.foo()如果构建器确实捕获了所有调用,则实际上调用变得不可能。那么您将无法再从构建器中调用本地方法。有很多尝试改变标准解决策略 - 也有很大的情感讨论。但最后,将“this”更改为引用嵌入类是解决问题的一个简单方法,并且更符合来自 Java 的人,而且如果您坚持,它可以让您轻松绕过 MOP。

于 2012-09-26T09:34:34.753 回答
9

看第144页

...this 指的是闭包,而不是声明对象。在这一点上,闭包对我们起到了作用。它们将所有方法调用委托给所谓的委托对象,默认情况下,委托对象恰好是声明对象(即所有者)。这使得闭包看起来好像封闭的代码在生日上下文中运行。

对于您的问题;

闭包内的 this 评估为调用闭包的范围?

从书中他们说“this指的是闭包,而不是声明对象”但是从bertport和我的实验来看,似乎“this”实际上是声明对象。

无论哪种方式,您的问题的答案仍然是“否”。

在上面显示的闭包中, this 和 caller 指的是相同的范围?

恐怕不是。

请注意,Groovy in Action 中的第 143 页和第 144 页需要一些更正

http://groovy.canoo.com/errata/erratum/show/5

http://groovy.canoo.com/errata/erratum/show/8

于 2009-05-04T13:49:30.873 回答
7
{
    def self = ({ owner })()
}

owner:封闭对象(this 或周围的Closure)。

于 2012-09-04T11:00:39.593 回答
1

Sake 说,“闭包,而不是构造闭包的对象。” 但是当我们运行这个脚本时,我们发现是一个Mother,而不是一个Closure。

于 2011-01-27T15:36:02.190 回答