Groovy 属性、访问方法、隐射和扩展(Fields/accessors/maps/Expand

在 groovy 的代码中,你经常发现如 object.name 这样的表达式,当 groovy 解释这样的引用的时候到底发生了什么:

 如果 object 引用到一个 map,object.name 引用到存储在 map 中的,key 值为name 对应的 value 值;

 否则,如果 name 是 object 的一个属性,那么这个属性被引用(优先采用访问方法,如 7.4.2 节所示);

 每 一 个 groovy 对 象 有 机 会 实 现 自 己 的 getProperty(name) 和 setProperty(name,value)方法,当这样做之后,这些实现用来控制属性的访问。例如,在 map 中使用这个机制来暴露 key 列表为属性列表;

 如 7.1.1 节显示,属性的访问能够通过提供 object.get(name)方法进行拦截,这 是 groovy 运行时被困扰的最后的对策:它仅仅用在没有适当的 javaBean 属性可用和 getProperty 方法没有实现的情况。

当属性包含特殊字符,而这些特殊字符是无效标识符的时候,这可以通过字符串来应用, 如 object.‘my-name’,你也可以使用 Gstring:def name = ‘my-name’; object. “$name”,正如你在 7.1.1 节所见,并且我们将在 9.1.1 节进行进一步的讨论,在 Object 上也有一个 getAt 的实现,这样你可以通过 object[name]的方式来访问对象的属性。

对于 groovy 对象解析依据决定了对象的动态状态和行为,groovy 带来了这样一个特性:Expando,一个 Expando 能够作为 bean 的扩展,尽管仅仅用于 groovy 中而没有直接用在 java 中,它支持 groovy 风格的属性访问和一些扩展,列表 7.22 显示了一个 Expando 对象如何通过赋值方式扩展属性,这与 map 相似,不同的时候将闭包赋值给一个 属性,这样在访问属性的时候闭包被执行,闭包可以接受任意参数,在这个例子中,boxer 的 fightBack 按给定的倍数返回。

在某种程度上,Expando 将闭包分配给属性的行为和通过属性访问存储的闭包有点像动态的增加方法给对象。

在避免写脏数据结构如类的时候,Map 和 Expand o 是极端的解决方案,因为它们不要求编写任何额外的类,在 groovy 中,访问 map 的 key 或者 Expando 的属性与访问 JavaBean 属性没有什么不同。但是这有代价的:Expando 不能在 java 中用作 b ean 并且不支持任何类型。