@Delegate
Java没有提供内置的代理机制,而到目前为止Groovy也没有提供。但借助于@Delegate,我们可以为类的属性加上注解使之成为接收方法调用的代理对象。在下面的示例中,Event类有个date代理,这样编译器就会将Event类上所有的Date方法调用代理给Date。如最后的assert所示,Event类拥有了before(Date)方法及Date的所有方法。
2
3 class Event {
4
5 @Delegate Date when
6
7 String title, url
8
9 }
10
11 def df = new SimpleDateFormat("yyyy/MM/dd")
12
13 def gr8conf = new Event(title: "GR8 Conference",
14
15 url: "http://www.gr8conf.org",
16
17 when: df.parse("2009/05/18"))
18
19 def javaOne = new Event(title: "JavaOne",
20
21 url: "http://java.sun.com/javaone/",
22
23 when: df.parse("2009/06/02"))
24
25 assert gr8conf.before(javaOne.when)
26
Groovy编译器将Date的所有方法加到了Event类中,这些方法仅仅是将调用代理给Date对象。如果代理不是final类,我们甚至还可以通过继承Date使得Event类成为Date的子类,如下所示。要想实现代理,我们无需将Date的所有方法和属性手动加到Event类中,因为编译器会帮我们处理这些事情。
2
3 @Delegate Date when
4
5 String title, url
6
7 }
8
假如要代理某个接口,那么你都无需显式实现该接口。@Delegate负责处理这些并实现该接口,这样,你的类的实例就自动成为代理的接口的实例了(instanceof )。
2
3 class LockableList {
4
5 @Delegate private List list = []
6
7 @Delegate private Lock lock = new ReentrantLock()
8
9 }
10
11 def list = new LockableList()
12
13 list.lock()
14
15 try {
16
17 list << 'Groovy'
18
19 list << 'Grails'
20
21 list << 'Griffon'
22
23 } finally {
24
25 list.unlock()
26
27 }
28
29 assert list.size() == 3
30
31 assert list instanceof Lock
32
33 assert list instanceof List
34
在该示例中,LockableList包含了一个list和一个lock,这样它就instanceof List和Lock了。如果不想让类实现这些接口,那么你可以通过指定注解参数来做到这一点:
@Delegate(interfaces = false) private List list = []