@Newify
@Newify提出了实例化类的两种新方式。第一种方式类似于Ruby,使用一个类方法new()来创建类:
2
3 assert Integer.new(42) == 42
4
5 }
6
7 rubyLikeNew()
8
第二种方式类似于Python,连关键字new都省略了。看看下面代码中Tree对象的创建过程:
2
3 def elements
4
5 Tree(Object... elements) { this.elements = elements as List }
6
7 }
8
9 class Leaf {
10
11 def value
12
13 Leaf(value) { this.value = value }
14
15 }
16
17 def buildTree() {
18
19 new Tree(new Tree(new Leaf(1), new Leaf(2)), new Leaf(3))
20
21 }
22
23 buildTree()
24
Tree对象的创建过程可读性太差,因为一行代码中出现了好几个new关键字。Ruby的方式也好不到哪去,因为还是要通过new()方法来创建每个元素。但借助于@Newify,我们可以改进Tree对象的创建过程使之可读性更好:
@Newify([Tree, Leaf]) buildTree() {
Tree(Tree(Leaf(1), Leaf(2)), Leaf(3))
}
你可能注意到了我们仅仅将@Newify加在了Tree和Leaf上。默认情况下,注解范围内的所有实例都是newified的,但你可以通过指定类来限定该范围。Groovy builder可能更适合该示例,因为其目的就是构建层级/树形的结构。
再来看看之前的那个coordinates示例,通过@Immutable和@Newify来创建一个path是多么的简洁,同时也是类型安全的:
2
3 Double latitude, longitude
4
5 }
6
7 @Immutable final class Path {
8
9 Coordinates[] coordinates
10
11 }
12
13 @Newify([Coordinates, Path])
14
15 def build() {
16
17 Path(
18
19 Coordinates(48.824068, 2.531733),
20
21 Coordinates(48.857840, 2.347212),
22
23 Coordinates(48.858429, 2.342622)
24
25 )
26
27 }
28
29 assert build().coordinates.size() == 3
30
这里我想多说几句:鉴于生成的是Path(Coordinates[] coordinates),我们可以通过Groovy中的可变参数方式来使用该构造方法,就好象其定义形式是这样的:Path(Coordinates... coordinates)。