使用 groovy 类别添加动态属性
Posted
技术标签:
【中文标题】使用 groovy 类别添加动态属性【英文标题】:Use groovy categories to add dynamic properties 【发布时间】:2013-02-12 05:42:30 【问题描述】:在this blog post 上进行扩展,我正在尝试使用一个类别来创建一个简单的 DSL,以便与javax.measure
(JSR-275) 类一起使用(类似于 TimeCategory 的时间间隔)
但是,我不想为每个可能的可用方法(getMeter、getMilliMeter、getKelvin、getSecond 等)添加样板代码。我认为覆盖 getProperty(String)
方法会起作用,但是,在直接访问属性时,似乎没有使用类别中定义的 getProperty
方法。
这里有一些简化的代码来演示: 导入 javax.measure.quantity.Length; 导入 javax.measure.unit.Unit; 导入 javax.measure.Measure;
@Category(Number)
class LengthCategory
public Measure<BigDecimal, Length> getProperty(String unit)
return Measure.valueOf(this,Unit.valueOf(unit));
use(LengthCategory)
println 3.getProperty("m") // this works
println 3.m // this reports a non-exisiting property
prinlln 3.'m' // as does this
假设其他动态添加属性到运行时对象的方法(例如Expando
、子类化GroovyInterceptible
、mixins 和其他元类操作)是不可行的,我真的宁愿不必为每个可能的单元手动编写getter 和SI 前缀组合。显然还有其他方法可以创建用于测量的 DSL,但我仍然想了解为什么这种方法不起作用。
有人可以解释为什么该类别的getProperty
方法不会覆盖.propertyName
的用法吗?我显然错过了在运行时使用元类解析属性名称的重要内容。
【问题讨论】:
【参考方案1】:我不知道为什么getProperty
不适用于类别。但是您可以在它们上定义一个基本相同的get
方法(我认为)。这有效:
@Category(Number)
class LengthCategory
def get(String unit)
"$this $unit"
use (LengthCategory)
println 3.m // 3 m
println 3.'m' // 3 m
【讨论】:
谢谢,这正是我想要的,但我仍然想知道为什么在类别中实现 getProperty(String name) 不起作用。【参考方案2】:据我所知,您实际上不能使用 Category 来扩展具有完整(即可读和可写)属性的整数——只能使用方法。
您可以通过使用属性的方法版本来使用只读属性扩展 Integer。您甚至可以通过包含 set 方法使其可写。但是,似乎没有办法将传入的值存储在静态变量中,这最终会影响所有整数。
例子:
$ cat catprop
#!/usr/local/bin/groovy
@Category(Integer)
class CatInteger
private static String str = "default"
public static String setN(Integer i, String _str) str = _str
public static String getN(Integer i) return str
use (CatInteger)
3.n = "333a"
println "3.n is " + 3.n
3.n = "333b"
println "3.n is " + 3.n
4.n = "444"
println "4.n is " + 4.n
println "3.n is " + 3.n
$ catprop
3.n is 333a
3.n is 333b
4.n is 444
3.n is 444
$
请注意,在最后一行 3.n 中返回“444”,因为存储的字段是静态的。我想可以使用私有 HashMap 并为每个访问的 Integer 存储一个值,但这太丑了,无法考虑。
另一种可能性是使用 MetaClass 接口的 getProperty() 和 setProperty()。但是,我还没有研究过,所以我不知道它是否可行(只是一个想法)。
【讨论】:
【参考方案3】:不错的答案,但不确定,既然 JSR-363 已经是最终版本,您是否仍想使用 JSR-275?;-)
【讨论】:
好点,但这是一个相当古老的问题。最初询问时,新的 JSR 帽子尚未获得批准。 没错。它指的是最新的示例/答案,不知道为什么它最终会出现在它上面?我们确实在github.com/unitsofmeasurement/uom-spaces/tree/master/… 下提供了对 JSR 363 的 Groovy 支持。与之前为 JSR 354 (JavaMoney) 所做的类似。以上是关于使用 groovy 类别添加动态属性的主要内容,如果未能解决你的问题,请参考以下文章