如何获取从Groovy特征继承的属性的java.reflect.Field值?

时间:2016-05-04 21:05:01

标签: grails reflection groovy traits

我在Grails Web应用程序中使用Groovy 2.4.3。我在其中声明了以下特征/类层次结构:

trait GuidData {
    String Guid
}

class Enrollment implements GuidData {
    String email
}

当我执行以下代码时,我得到了预期的结果:

Enrollment enrollment = new Enrollment(email: "joe@tester.com", guid: "XXXX")
assert enrollment.properties == ['email':'joe@tester.com', 'guid':'XXXX']
assert enrollment.getProperty("guid") == "XXXX")
Enrollment.getDeclaredField("email") == private java.lang.String Enrollment.email

但是当我执行方法时:

Enrollment.getDeclaredField("guid")

我收到NoSuchFieldException。如果我为“getEmail”方法执行“getDeclaredMethod()”,我正确地得到了一个java.reflect.Method实例。

所以...看起来在特征中定义的Groovy属性显示为Groovy属性,并且可以像在父类中定义的属性一样被引用,但它们不会在标准Groovy属性中反映为具有getter / setter的字段图案。换句话说,如果属性出现在对getProperties()的实例调用中,我希望反射调用也可以使Field定义工作。

1 个答案:

答案 0 :(得分:3)

来自Groovy documentation on Traits,特别是公共字段(如下文Burt所述,这也适用于属性):

  

...为了避免diamond problem,在实现类中重新映射字段名...

继续:

  

字段的名称取决于特征的完全限定名称。包中的所有点(。)都用下划线(_)替换,最终名称包含双下划线。因此,如果字段的类型是String,则包的名称是my.package,特征的名称是Foo,字段的名称是bar,在实现类中,公共字段将显示为:{{ 1}}。

因此,对于实现String my_package_Foo__bar的{​​{1}}类,它没有名为Enrollment的字段,它有一个名为GuidData的字段(假设为Guid }不在包中)。这就是你遇到GuidData__Guid的原因。这应该有效:

Enrollment

NoSuchFieldException类确实有getter / setters Enrollment.getDeclaredField("GuidData__Guid") Enrollment,这就是您可以使用常规属性访问器或使用常规getter语法访问它的方法。