使用Groovy类别添加动态属性

5

这篇博客文章的基础上,我正在尝试使用类别为javax.measure (JSR-275)类创建一个简单的DSL(与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、混合和其他元类操作)不可行,我真的不想手动编写每个可能的单位和SI前缀组合的getter。显然,创建测量DSL的其他方法,但我仍然希望了解为什么这种方法不起作用。
有人能解释一下为什么类别的getProperty方法没有覆盖.propertyName使用吗?在运行时期间使用元类解析属性名称时,我显然漏掉了一些重要内容。
3个回答

5

我不知道为什么在类别上使用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)方法不起作用。 - RudolphEst

0
据我所知,您无法使用Category实际扩展带有完整(即可读和可写)属性的Integers,只能使用方法。
您可以使用属性的方法版本来扩展Integer的只读属性。甚至可以通过包含set方法使其可写。但是,似乎没有其他存储传递值的方法,除了在静态变量中存储,这最终会影响所有Integers。
例如:
$ 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并为每个访问的整数存储一个值,但这太丑陋了,不值得考虑。
另一个可能性是使用MetaClass接口的getProperty()和setProperty()。然而,我还没有研究过它是否可行(只是一个想法)。

0
很好的回答,但不确定您是否仍然想要使用JSR-275,现在JSR-363已经最终确定了吗?;-)

很好的一点,但这是一个相当旧的问题。最初提问时,新的JSR尚未得到批准。 - RudolphEst
没错。它指的是最新的示例/答案,不确定为什么它会出现在上面?我们在https://github.com/unitsofmeasurement/uom-spaces/tree/master/groovy-space为JSR 363提供了Groovy支持。就像之前为JSR 354(JavaMoney)所做的那样。 - Werner Keil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接