Groovy探索之delegate关键字 一(2)
2008-10-27 08:11
363 查看
这个例子首先要从一个GroovyBean说起:
class Person
{
String name
}
这是一个很简单的GroovyBean类,下面,我们为这个GroovyBean类做了一个Builder类,如下:
class PersonBuilder {
def persons = []
def persons(Closure closure)
{
closure.delegate = this
closure()
return this.persons
}
def getProperty(String propertyName)
{
this.persons<<new Person(name:"${propertyName}")
}
}
先不要看这个builder类,我们先来看看如何使用这个builder类,我们在“PersonBuilder”类里加入如下的一个“main”方法:
static void main(args) {
def pers = new PersonBuilder().persons{
mike
alice
tom
mark
}
pers.each{
println it.name
}
}
这个“main”方法的运行结果为:
mike
alice
tom
mark
正是这个很简单的功能,却完完整整的为我们演示了“delegate”关键字的功能。我们首先来看“main”方法。
我们为“PersonBuilder”类的“persons”方法传入了如下的一个闭包:
{
mike
alice
tom
mark
}
下面,我们来看“PersonBuilder”类的“persons”方法:
def persons(Closure closure)
{
closure.delegate = this
closure()
return this.persons
}
我们先不管第一个语句行:“closure.delegate = this”,来看第二个语句行:
closure()
即执行传入的闭包。那么闭包里有些什么语句呢?很简单,就是执行四个变量:
mike
alice
tom
mark
值得注意的是,这个四个变量没有任何关键字来修饰,前面我们说过,如果闭包里的变量没有任何关键字来修饰,那么首先看闭包里有没有把该变量定义成local变量,我们可以再看看传入的闭包,没有在闭包的任何地方把它们四个变量定义成local变量。所以这个四个语句行就相当于下面的四个语句行:
delegete.mike
delegete.alice
delegete.tom
delegete.mark
学过Gpath的人都知道,在Groovy语言中,“delegete.mike”相当于如下的调用如下的语句:
delegate.getMike()
另外的三个语句如此类推。这就意味着我们希望在“PersonBuilder”类中有“getMike”这类的方法。我们再看看“PersonBuilder”类,虽然没有显式的“getMike”这类的方法,但是有一个“getProperty”方法。我们知道,在Groovy语言中,“getProperty”方法会分派所有的“get”方法,不管是“getMike”还是“getAlice”,都会调用“getProperty”方法。
所以,通过以上的分析,我们闭包的四个语句都会调用“getProperty”方法。而“getProperty”方法干了些什么事呢?
this.persons<<new Person(name:"${propertyName}")
看看上面的语句,很简单,就是以闭包里的变量名作为参数,来实例化一个Person类对象,然后把这个对象add到一个名为“persons”的List对象里存起来。
到目前为止,我们已经分析了“PersonBuilder”类的工作原理,但却漏掉了一个最重要的要点,没有它,这个“PersonBuilder”类的构思再好,也是实现不了的。那么这个要点是什么呢?
我们在谈“PersonBuilder”类的“persons”方法的时候,放下了第一个语句行:
closure.delegate = this
那么,这个语句行有什么用呢?
我们还是可以先做一个测试,将这个语句行从“PersonBuilder”类中注销掉,那么,“PersonBuilder”类就变成了下面的样子:
class PersonBuilder {
def persons = []
def persons(Closure closure)
{
//closure.delegate = this
closure()
return this.persons
}
def getProperty(String propertyName)
{
this.persons<<new Person(name:"${propertyName}")
}
static void main(args) {
def pers = new PersonBuilder().persons{
mike
alice
tom
mark
}
pers.each{
println it.name
}
}
}
现在,我们运行上面的“main”方法,结果如下:
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: mike for class: PersonBuilder
at groovy.lang.MetaClassImpl.invokeStaticMissingProperty(MetaClassImpl.java:730)
这个Exception很长,我只截取了前面两句话。为什么会抛出“No such property”的错误呢?
我们再来看看“main”方法,发现闭包:
{
mike
alice
tom
mark
}
是定义在“main”方法里的,而“main”方法是一个静态方法,而我们前面说过,像“mike”这样的语句相当于“delegete.mike”。基于这个一个原因,“delegete.mike”中的“delegate”肯定指向“PersonBuilder”类,而“delegete.mike”语句肯定会调用“PersonBuilder”类的静态的“getMike”方法。
而上面的“PersonBuilder”类中没有静态的“getMike”这类的方法,当然就会报“No such property”的错误了。
基于这样的分析,如果我们在上面的“PersonBuilder”类加入如下的静态方法:
def static getMike()
{
this.persons<<new Person(name:"mike")
}
那么,是不是在执行闭包里的“mike”语句行时,就不会报错了呢?
我们把“getMike()”方法加入到“PersonBuilder”类中,然后,再将“persons”变量也变成静态变量。如下所示:
class PersonBuilder {
def static persons = []
def persons(Closure closure)
{
//closure.delegate = this
closure()
return persons
}
def getProperty(String propertyName)
{
persons<<new Person(name:"${propertyName}")
}
def static getMike()
{
persons<<new Person(name:"mike")
}
static void main(args) {
def pers = new PersonBuilder().persons{
mike
alice
tom
mark
}
pers.each{
println it.name
}
}
}
执行,结果为:
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: alice for class: delegateBuilder.PersonBuilder
at groovy.lang.MetaClassImpl.invokeStaticMissingProperty(MetaClassImpl.java:730)
可以看到,“No such property”的错误是报在“alice”变量的上面。这说明,“mike”可以正常的执行了。
现在,我们就基本上可以猜测“closure.delegate = this”语句行的作用了。由于闭包“closure”是定义在静态方法中,我们当然希望它定义在非静态方法中,而闭包的“delegate”变量又刚好是可以改变的。
所以,我们通过“closure.delegate = this”语句行来改变闭包的“delegate”变量的指向,将它指向“this”,而刚好“this”又是指向当前对象的。这就使得闭包定义在一个非静态方法里。就使得闭包中的语句行可以使用“getProperty”方法了。而我们的“PersonBuilder”类达到了我们要想的目的。
可以说,这个例子是一个很好的使用了闭包关键字“delegate”的例子。虽然我们不会在实际中使用这个例子,但它给我们的启示依然是很重要的。我们很好的理解了这个例子,才可以在实际的编程中灵活的使用闭包的“delegate”关键字。
class Person
{
String name
}
这是一个很简单的GroovyBean类,下面,我们为这个GroovyBean类做了一个Builder类,如下:
class PersonBuilder {
def persons = []
def persons(Closure closure)
{
closure.delegate = this
closure()
return this.persons
}
def getProperty(String propertyName)
{
this.persons<<new Person(name:"${propertyName}")
}
}
先不要看这个builder类,我们先来看看如何使用这个builder类,我们在“PersonBuilder”类里加入如下的一个“main”方法:
static void main(args) {
def pers = new PersonBuilder().persons{
mike
alice
tom
mark
}
pers.each{
println it.name
}
}
这个“main”方法的运行结果为:
mike
alice
tom
mark
正是这个很简单的功能,却完完整整的为我们演示了“delegate”关键字的功能。我们首先来看“main”方法。
我们为“PersonBuilder”类的“persons”方法传入了如下的一个闭包:
{
mike
alice
tom
mark
}
下面,我们来看“PersonBuilder”类的“persons”方法:
def persons(Closure closure)
{
closure.delegate = this
closure()
return this.persons
}
我们先不管第一个语句行:“closure.delegate = this”,来看第二个语句行:
closure()
即执行传入的闭包。那么闭包里有些什么语句呢?很简单,就是执行四个变量:
mike
alice
tom
mark
值得注意的是,这个四个变量没有任何关键字来修饰,前面我们说过,如果闭包里的变量没有任何关键字来修饰,那么首先看闭包里有没有把该变量定义成local变量,我们可以再看看传入的闭包,没有在闭包的任何地方把它们四个变量定义成local变量。所以这个四个语句行就相当于下面的四个语句行:
delegete.mike
delegete.alice
delegete.tom
delegete.mark
学过Gpath的人都知道,在Groovy语言中,“delegete.mike”相当于如下的调用如下的语句:
delegate.getMike()
另外的三个语句如此类推。这就意味着我们希望在“PersonBuilder”类中有“getMike”这类的方法。我们再看看“PersonBuilder”类,虽然没有显式的“getMike”这类的方法,但是有一个“getProperty”方法。我们知道,在Groovy语言中,“getProperty”方法会分派所有的“get”方法,不管是“getMike”还是“getAlice”,都会调用“getProperty”方法。
所以,通过以上的分析,我们闭包的四个语句都会调用“getProperty”方法。而“getProperty”方法干了些什么事呢?
this.persons<<new Person(name:"${propertyName}")
看看上面的语句,很简单,就是以闭包里的变量名作为参数,来实例化一个Person类对象,然后把这个对象add到一个名为“persons”的List对象里存起来。
到目前为止,我们已经分析了“PersonBuilder”类的工作原理,但却漏掉了一个最重要的要点,没有它,这个“PersonBuilder”类的构思再好,也是实现不了的。那么这个要点是什么呢?
我们在谈“PersonBuilder”类的“persons”方法的时候,放下了第一个语句行:
closure.delegate = this
那么,这个语句行有什么用呢?
我们还是可以先做一个测试,将这个语句行从“PersonBuilder”类中注销掉,那么,“PersonBuilder”类就变成了下面的样子:
class PersonBuilder {
def persons = []
def persons(Closure closure)
{
//closure.delegate = this
closure()
return this.persons
}
def getProperty(String propertyName)
{
this.persons<<new Person(name:"${propertyName}")
}
static void main(args) {
def pers = new PersonBuilder().persons{
mike
alice
tom
mark
}
pers.each{
println it.name
}
}
}
现在,我们运行上面的“main”方法,结果如下:
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: mike for class: PersonBuilder
at groovy.lang.MetaClassImpl.invokeStaticMissingProperty(MetaClassImpl.java:730)
这个Exception很长,我只截取了前面两句话。为什么会抛出“No such property”的错误呢?
我们再来看看“main”方法,发现闭包:
{
mike
alice
tom
mark
}
是定义在“main”方法里的,而“main”方法是一个静态方法,而我们前面说过,像“mike”这样的语句相当于“delegete.mike”。基于这个一个原因,“delegete.mike”中的“delegate”肯定指向“PersonBuilder”类,而“delegete.mike”语句肯定会调用“PersonBuilder”类的静态的“getMike”方法。
而上面的“PersonBuilder”类中没有静态的“getMike”这类的方法,当然就会报“No such property”的错误了。
基于这样的分析,如果我们在上面的“PersonBuilder”类加入如下的静态方法:
def static getMike()
{
this.persons<<new Person(name:"mike")
}
那么,是不是在执行闭包里的“mike”语句行时,就不会报错了呢?
我们把“getMike()”方法加入到“PersonBuilder”类中,然后,再将“persons”变量也变成静态变量。如下所示:
class PersonBuilder {
def static persons = []
def persons(Closure closure)
{
//closure.delegate = this
closure()
return persons
}
def getProperty(String propertyName)
{
persons<<new Person(name:"${propertyName}")
}
def static getMike()
{
persons<<new Person(name:"mike")
}
static void main(args) {
def pers = new PersonBuilder().persons{
mike
alice
tom
mark
}
pers.each{
println it.name
}
}
}
执行,结果为:
Exception in thread "main" groovy.lang.MissingPropertyException: No such property: alice for class: delegateBuilder.PersonBuilder
at groovy.lang.MetaClassImpl.invokeStaticMissingProperty(MetaClassImpl.java:730)
可以看到,“No such property”的错误是报在“alice”变量的上面。这说明,“mike”可以正常的执行了。
现在,我们就基本上可以猜测“closure.delegate = this”语句行的作用了。由于闭包“closure”是定义在静态方法中,我们当然希望它定义在非静态方法中,而闭包的“delegate”变量又刚好是可以改变的。
所以,我们通过“closure.delegate = this”语句行来改变闭包的“delegate”变量的指向,将它指向“this”,而刚好“this”又是指向当前对象的。这就使得闭包定义在一个非静态方法里。就使得闭包中的语句行可以使用“getProperty”方法了。而我们的“PersonBuilder”类达到了我们要想的目的。
可以说,这个例子是一个很好的使用了闭包关键字“delegate”的例子。虽然我们不会在实际中使用这个例子,但它给我们的启示依然是很重要的。我们很好的理解了这个例子,才可以在实际的编程中灵活的使用闭包的“delegate”关键字。
相关文章推荐
- Groovy探索之delegate关键字 一(1)
- Groovy探索之Delegate模式 二
- Groovy探索 “as”关键字的深入使用
- Groovy探索之Delegate模式 一
- Groovy探索之Delegate模式 三
- Groovy探索之Gstring
- Groovy探索之Map与DSL
- Groovy探索 Visitor模式
- C#中yield关键字用法(以及delegate/Lambde/Linq之间的关系)
- Groovy探索之MOP 五 针对接口类型的动态性
- Groovy探索之MOP 十二 方法的调用顺序
- 深入探索面向对象事件(Delegate)机制
- delegate & event 关键字
- Groovy探索之闭包 二
- C++中extern “C”含义深层探索及extern、static关键字浅析
- Groovy探索之invokeMethod方法
- Groovy探索之Builder 一
- Groovy探索之闭包 四
- Groovy探索之运算符的重载 二
- Groovy探索 对字符串编写Groovy风格的代码