Groovy Transformation:@Delegate

Groovy Transformation是一种编译时改变类的技术,作为本系列的第一小节,我们先来看看@Delegate。

熟悉设计模式的读者应该对Delegate模式不会陌生,虽然.net中已经对Delegate在语言层面上提供了支持,但遗憾的是Java中并没有,Groovy也是同样如此。但是,从Groovy 1.6起,我们可以使用@Delegate来弥补这种遗憾。

@Delegate应用在类的属性和字段上,被应用者就成为一个方法的被委托者。看看例子:

class AnotherDate{
    @Delegate Date internal
}
def d= new Date()
def ad= new AnotherDate(internal: d)

assert ad.time == d.time

@Delegate背后的机制很简单:在编译时,被注解字段(属性)所属类型的所有非私有且没有出现在目标类中的方法,都被复制到目标类。缺省不会复制有@Deprecated的方法,但是可以使用以下方法:

class AnotherDate{
    @Delegate(deprecated=true) Date internal
}
def d= new Date()
def ad= new AnotherDate(internal: d)

assert ad.year == d.year

缺省情况下,目标类会被修改成实现委托类接口,如对前面例子,以下成立:

assert ad instanceof Cloneable

但是,使用以下方式,则以上不成立:

class AnotherDate{
    @Delegate(interfaces=false) Date internal
}
def d= new Date()
def ad= new AnotherDate(internal: d)

assert !(ad instanceof Cloneable)

委托对象还可以有多个:

class ListAndDate {
    @Delegate List list
    @Delegate Date date
}
def d= new Date()
def ld= new ListAndDate(list:[], date: d)
ld << 'Groovy'
assert ld.size() == 1
assert ld.time == d.time

当然,你也可以定义自己的委托对象:

class Greeting{
    def hello(){return "Hello!" }
}
class Man{
    def name
    @Delegate Greeting greeting
}
def man= new Man(name:'foxgem', greeting: new Greeting())
assert man.hello() == 'Hello!'

如果使用了多个委托对象,且它们有同样方法,那么以第一个为准:

class Greeting1{
    def hello(){return "Hello 1!" }
}
class Greeting2{
    def hello(){return "Hello 2!" }
}
class Man{
    @Delegate Greeting1 greeting1
    @Delegate Greeting2 greeting2
}
def man= new Man(greeting1: new Greeting1(),
                 greeting2: new Greeting2())
assert man.hello() == 'Hello 1!'

By foxgem - Posted on 04 二月 2010

这跟.net的delegate不一样吧?而且好像差很远 

这跟.net的delegate不一样吧?而且好像差很远 

作用相似

没有说是一样呀,作用是相似的吧。

这个功能不错,挺有意思,哈哈

这个功能不错,挺有意思,哈哈

这个应该是mixin,delegate也是字面上的意思委托

这个应该是mixin,delegate也是字面上的意思委托给这个对象...

可以这么说。

对,可以这么说。javascript中有一种继承实现也是这样的思路,具体哪个库,忘了。;)