我在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定义工作。
答案 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语法访问它的方法。