技术开发 频道

Groovy 1.6的新特性

  @Newify

  @Newify提出了实例化类的两种新方式。第一种方式类似于Ruby,使用一个类方法new()来创建类:

1 @Newify rubyLikeNew() {
2
3   assert Integer.new(42) == 42
4
5   }
6
7   rubyLikeNew()
8

  第二种方式类似于Python,连关键字new都省略了。看看下面代码中Tree对象的创建过程:

1 class 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是多么的简洁,同时也是类型安全的:

1 @Immutable final class Coordinates {
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)。

1