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!'

这跟.net的delegate不一样吧?而且好像差很远
这跟.net的delegate不一样吧?而且好像差很远
作用相似
没有说是一样呀,作用是相似的吧。
这个功能不错,挺有意思,哈哈
这个功能不错,挺有意思,哈哈
这个应该是mixin,delegate也是字面上的意思委托
这个应该是mixin,delegate也是字面上的意思委托给这个对象...
可以这么说。
对,可以这么说。javascript中有一种继承实现也是这样的思路,具体哪个库,忘了。;)