扩展this blog post,我试图使用一个类别来创建一个简单的DSL,用于javax.measure
(JSR-275)类(类似于TimeCategory的时间间隔)
但是,我不想为每种可能的方法(getMeter,getMilliMeter,getKelvin,getSecond等)添加样板代码。我认为覆盖getProperty(String)
方法会起作用,但唉,看起来直接访问属性时不会使用类别中定义的getProperty
方法。
以下是一些简化的代码来演示: import javax.measure.quantity.Length; import javax.measure.unit.Unit; import 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 for每个可能的单位和SI前缀组合。显然还有其他方法可以为测量创建DSL,但我仍然想了解为什么这种方法不起作用。
有人可以解释为什么该类别的getProperty
方法不会覆盖.propertyName
用法吗?我显然遗漏了在运行时使用元类解析属性名称的重要事项。
答案 0 :(得分:4)
我不知道为什么getProperty
不适用于类别。但是你可以在它们上定义一个基本相同的get
方法(我认为)。这有效:
@Category(Number)
class LengthCategory {
def get(String unit) {
"$this $unit"
}
}
use (LengthCategory) {
println 3.m // 3 m
println 3.'m' // 3 m
}
答案 1 :(得分:0)
据我所知,你实际上不能使用Category来扩展具有完整(即可读和可写)属性的Integers - 仅使用方法。
您可以使用属性的方法版本,使用只读属性扩展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()。但是,我没有调查过,所以我不知道它是否会起作用(只是一个想法)。
答案 2 :(得分:0)
很好的答案,但不确定,如果你现在还想使用JSR-275 JSR-363是最终的?; - )