Groovy Closures this owner delegate 的含义
this corresponds to the enclosing class where the closure is defined
owner corresponds to the enclosing object where the closure is defined, which may be either a class or a closure
delegate corresponds to a third party object where methods calls or properties are resolved whenever the receiver of the message is not defined
要想了解Groovy闭包中的this,owner和delegate的含义,首先我们需要知道闭包能在哪些上下文中进行创建。
首先,闭包可以在方法体中创建(类的实例方法或者静态方法均可)
closures_app2.groovy
class Student { def static method() { def methodClosure = { println "methodClosure this:" + this println "methodClosure owner:" + owner println "methodClosure delegate:" + delegate } methodClosure } } Student.method().call()
运行输出,
methodClosure this:class com.usoft.Student
methodClosure owner:class com.usoft.Student
methodClosure delegate:class com.usoft.Student
其次, 闭包可以在类中直接定义:
closures_app2.groovy
class HelloWorld { def static classClosure = { println "classClosure this:" + this println "classClosure owner:" + owner println "classClosure delegate:" + delegate } } HelloWorld.classClosure.call()
运行输出如下,
classClosure this:class com.usoft.HelloWorld
classClosure owner:class com.usoft.HelloWorld
classClosure delegate:class com.usoft.HelloWorld
再者,闭包可以在groovy的script中直接定义,实际上也是在类中直接定义,同上,因为groovy的script实际上会被编译为Script.class
closures_app2.groovy
def scriptClosure = { println "scriptClosure this:" + this println "scriptClosure owner:" + owner println "scriptClosure delegate:" + delegate } scriptClosure.call()
运行输出如下,
scriptClosure this:com.usoft.closures_app2@1a451d4d scriptClosure owner:com.usoft.closures_app2@1a451d4d scriptClosure delegate:com.usoft.closures_app2@1a451d4d
最后, 闭包可以在闭包中定义:
closures_app2.groovy
def closure = { def closureClosure = { println "closureClosure this:" + this println "closureClosure owner:" + owner println "closureClosure delegate:" + delegate } closureClosure.call() } closure.call()
运行并输出,
closureClosure this:com.usoft.closures_app2@15ff3e9e
closureClosure owner:com.usoft.closures_app2$_run_closure2@3ce1e309
closureClosure delegate:com.usoft.closures_app2$_run_closure2@3ce1e309
从上可以看到,闭包可以在四种上下文中进行定义,但是闭包中的this,owner 和 delegate的含义却各不相同。
如下代码,closures_app3.groovy
package com.usoft /** * @author: Lenovo ( 2015 - 04 - 19 22 : 09 ) */ class ClosureTest { /** * 类的静态闭包 */ def static classClosure = { println "classClosure this:" + this println "classClosure owner:" + owner println "classClosure delegate:" + delegate } /** * 类的实例闭包 */ def instanceClosure = { println "instanceClosure this:" + this println "instanceClosure owner:" + owner println "instanceClosure delegate:" + delegate } /** * 静态方法中的闭包 * @return */ def static classMethodClosure() { def classMethodClosure = { println "classMethodClosure this:" + this println "classMethodClosure owner:" + owner println "classMethodClosure delegate:" + delegate } classMethodClosure.call() } /** * 实例方法中的闭包 * @return */ def instanceMethodClosure() { def instanceMethodClosure = { println "instanceMethodClosure this:" + this println "instanceMethodClosure owner:" + owner println "instanceMethodClosure delegate:" + delegate } instanceMethodClosure.call() } } println "=======================" ClosureTest.classClosure() println "=======================" new ClosureTest().instanceClosure() println "=======================" ClosureTest.classMethodClosure() println "=======================" new ClosureTest().instanceMethodClosure()
运行并输出,
=======================
classClosure this:class com.usoft.ClosureTest
classClosure owner:class com.usoft.ClosureTest
classClosure delegate:class com.usoft.ClosureTest
=======================
instanceClosure this:com.usoft.ClosureTest@8dbdac1
instanceClosure owner:com.usoft.ClosureTest@8dbdac1
instanceClosure delegate:com.usoft.ClosureTest@8dbdac1
=======================
classMethodClosure this:class com.usoft.ClosureTest
classMethodClosure owner:class com.usoft.ClosureTest
classMethodClosure delegate:class com.usoft.ClosureTest
=======================
instanceMethodClosure this:com.usoft.ClosureTest@74e52303
instanceMethodClosure owner:com.usoft.ClosureTest@74e52303
instanceMethodClosure delegate:com.usoft.ClosureTest@74e52303
对于this来讲,它基本上保持了跟java中this一样的含义(在java的静态方法以及静态域中,this是没有任何含义的),在上面的闭包创建的4种上下文中,实际上可以认为只有2种,一种是在普通的类中定义,如上面的Person类,一种是在groovy script中定义,实际上也是在类中定义,只不过这个是一个比较特殊的类而已, 所以,this在闭包中的含义指的是,表示定义该闭包的类的实例对象(实例闭包)或者类本身(静态闭包)。
对于owner来讲,它的含义基本上跟this的含义一样,只是除了一种情况,如果该闭包是在其他的闭包中定义的,那么owner是指向定义它的闭包对象。 如上面最后一种创建上下文:
闭包可以在闭包中定义:
closures_app2.groovy
def closure = { def closureClosure = { println "closureClosure this:" + this println "closureClosure owner:" + owner println "closureClosure delegate:" + delegate } closureClosure.call() } closure.call()
运行并输出,
closureClosure this:com.usoft.closures_app2@15ff3e9e
closureClosure owner:com.usoft.closures_app2$_run_closure2@3ce1e309
closureClosure delegate:com.usoft.closures_app2$_run_closure2@3ce1e309
对于delegate来讲,它的含义大多数情况下是跟owner的含义一样,除非它被显示的修改(通过Closure.setDelegate()方法进行修改)。
在上面的几种创建上下文中,可以看到,如果闭包的delegate没有被显示改动的话,那么delegate确实是同owner是一个含义。下面我们看看修改delegate的情况:
closures_app4.groovy
package com.usoft /** * @author: Lenovo ( 2015 - 04 - 19 22 : 20 ) */ def scriptClosure = { println "scriptClosure this:" + this println "scriptClosure owner:" + owner println "scriptClosure delegate:" + delegate } println "before setDelegate()" scriptClosure.call() scriptClosure.setDelegate("abc") println "after setDelegate()" scriptClosure.call()
运行并输出,
before setDelegate()
scriptClosure this:com.usoft.closures_app4@7714e963
scriptClosure owner:com.usoft.closures_app4@7714e963
scriptClosure delegate:com.usoft.closures_app4@7714e963
after setDelegate()
scriptClosure this:com.usoft.closures_app4@7714e963
scriptClosure owner:com.usoft.closures_app4@7714e963
scriptClosure delegate:abc
其中,delegate可以被设置为任意一个对象。
下面可以看下groovy中使用了setDelegate的应用:
package com.usoft /** * @author: Lenovo ( 2015 - 04 - 19 22 : 22 ) */ String.metaClass.doTestClosure = { println "doTestClosure this:" + this println "doTestClosure owner:" + owner println "doTestClosure delegate:" + delegate } "do test".doTestClosure() Integer.metaClass.doTestClosure = { println "doTestClosure this:" + this println "doTestClosure owner:" + owner println "doTestClosure delegate:" + delegate } 1.doTestClosure()
运行并输出,
doTestClosure this:com.usoft.closures_app5@67d48005
doTestClosure owner:com.usoft.closures_app5@67d48005
doTestClosure delegate:do test
doTestClosure this:com.usoft.closures_app5@67d48005
doTestClosure owner:com.usoft.closures_app5@67d48005
doTestClosure delegate:1
可以看到,在通过metaClass动态添加方法时,delegate都被动态的设置为了调用者的实例本身,如上面的"do test"字符窜,以及整数1.
setDelegate还被广泛的使用于groovy builder的构建中。有兴趣的可以看下groovy中BuildSupport的实现。