【问题标题】:Use groovy categories to add dynamic properties使用 groovy 类别添加动态属性
【发布时间】: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 的用法吗?我显然错过了在运行时使用元类解析属性名称的重要内容。

【问题讨论】:

    标签: groovy metaclass


    【解决方案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) 所做的类似。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-13
      • 2019-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多