First they ignore you
then they ridicule you
then they fight you
then you win
    -- Mahatma Gandhi
Chinese => English     英文 => 中文             
随笔-221  评论-1047  文章-0  trackbacks-0
曾经很多Groovy开发者问我closure中的delegate是什么,有什么作用?

其实closure中的delegate类似于类中的this,让我们看一个小例子,大家就清楚了 :)

class DelegateDemo {
    String author 
= "山风小子"

    def someMethod(closure) {
        println 
"The original delegate of closure is: ${closure.delegate}"
        closure.delegate 
= this
        closure()
    }

    def greet(words) {
        println words
    }
}

def delegateDemo 
= new DelegateDemo()
delegateDemo.someMethod {
    
// 此处的delegate可以省略
    delegate.greet("Hello, " + delegate.author)
}
delegateDemo.someMethod {
    
// 省略了delegate
    greet("Hello, " + author)
}
运行结果:
The original delegate of closure is: Script16@13e6346
Hello, 山风小子
The original delegate of closure is: Script16@13e6346
Hello, 山风小子
注意:可能大家运行结果中的‘Script16@13e6346’部分各不相同,但都是Script开始的一个类名(我这里的类名为Script16)

在类的实例方法中调用方法和引用属性时,我们可以省略方法或属性前this(比如this.method(),this.property可简写为method(),property),
表示调用或引用的是本实例的方法或属性。
类似地,在closure中调用方法和引用属性时,我们也可以省略方法和属性前的delegate,
表示调用或引用的是本closure的方法或属性(而closure通过delegate隐式变量将方法调用和变量引用‘委派’给了delegate引用的那个对象)

那closure的delegate的默认值是什么呢?默认值是closure所在context中的this(为了方便理解起见,可以暂时这么记忆,因为closure套closure的情况不是很多见。其实closure的delegate的默认值是closure的隐式变量owner,而owner通常引用closure所在context中的this,除非closure所处的context又是个closure,那么owner引用的就是那个外层的closure,关于closure中的owner,我将在下篇文章《Groovy解惑——closure中的owner》中进行讲解),让我再用一个例子来说明一下吧:
class DelegateDemo {
    String author 
= "山风小子"

    def someMethod2(closure) {
        println 
"The original delegate of closure is: ${closure.delegate}"
        
// 无需设置closure.delegate,因为closure的delegate默认值已经是DelegateDemo.this
        
//closure.delegate = this
        closure()
    }

    def greet(words) {
        println words
    }

    def test() {
        def delegateDemo 
= new DelegateDemo()
        
// 传入someMethod2的closure {} 所处的context的this是DelegateDemo.this
        
// 所以closure的delegate的默认值也是DelegateDemo.this
        delegateDemo.someMethod2 {
            
// 此处的delegate可以省略
            delegate.greet("Hello, " + delegate.author)
        }
        delegateDemo.someMethod2 {
            
// 省略了delegate
            greet("Hello, " + author)
        }
    }
}

def dd 
= new DelegateDemo()
dd.test()

运行结果:
The original delegate of closure is: DelegateDemo@1b5d2b2
Hello, 山风小子
The original delegate of closure is: DelegateDemo@1b5d2b2
Hello, 山风小子
注意DelegateDemo.this是Java中的表示方法,在Groovy并不支持,这么写是为了方便Java开发人员理解 :)
由于第一个例子中的closure所处的context中的this是Script16.this,类Script16是没有author属性和greet方法的,所以我们必须设置delegate

希望经过我这么一解释,大家对closure的delegate有所认识,清楚区分delegate和this :)


附:朝花夕拾——Groovy & Grails


posted on 2007-12-22 15:50 山风小子 阅读(5358) 评论(1)  编辑  收藏 所属分类: Groovy & Grails