以前我认为 Groovy 中的属性是通过省略作用域关键字来指示的。换句话说

class Test {
   def prop = "i am a property"
   public notProp = "i am not"
}

但是,看来我对此不正确,因为以下脚本打印“getter val”

class Foo {
  public bar = "init val"

  public getBar() {
    "getter val"
  }
}

println new Foo().bar

bar访问时调用 getter 的事实表明这bar是一个属性而不是字段。那么 Groovy 中的字段和属性到底有什么区别呢?

谢谢,唐


为了直接访问字段,您必须在其前面添加 @ 符号:

assert "getter val" == new Foo().bar
assert "init val" == new Foo().@bar

作品的简短形式new Foo().getBar()虽然bar不是一种财产,但在我看来仍然是简洁的。

相反,您无法调用foo.setBar("setter val"),但如果您将其定义bar为不带访问修饰符的属性,则可以调用。



使用修饰符确实会抑制属性的创建。让您感到困惑的是,.当不存在这样的属性时,似乎会回退到字段访问。

$ 格罗维什
Groovy 外壳(2.1.0,JVM:1.7.0_21)
输入“help”或“\h”以获得帮助。
-------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ----------------------------
groovy:000> 类 A { def a = "foo" };
===> 正确
groovy:000> 新 A().getA()
===> 富
groovy:000> 新 A().a
===> 富
groovy:000> 新 A().properties
===> {class=A 类,a=foo}

但:

groovy:000> 类 A { public def a = "foo" };
===> 正确
groovy:000> 新 A().getA()
错误 groovy.lang.MissingMethodException:
无方法签名:A.getA() 适用于参数类型:() 值:[]
可能的解决方案: getAt(java.lang.String)、grep()、grep(java.lang.Object)、with(groovy.lang.Closure)、putAt(java.lang.String、java.lang.Object)、等待()
        在 groovysh_evaluate.run (groovysh_evaluate:2)
        ...
groovy:000> 新 A().a
===> 富
groovy:000> 新 A().properties
===> {类=A类}

我认为@Christoph Metzendorf 的答案是正确的......

为了直接访问字段,您必须在其前面添加 @ 符号:

assert "getter val" == new Foo().bar
assert "init val" == new Foo().@bar

...但我想补充一点,在您的Foo示例中,您的getBar方法覆盖了getBarGroovy 为您生成的方法。bar如果您想继续覆盖 Groovy 为您生成的默认方法,您可以使用上述语法直接访问getBar,或者您可以不覆盖,getBar这样任何调用都getBar将使用 Groovy 为您生成的 getter。


它们可能看起来相同并且大部分行为相同,但 Groovy 只会为属性生成 getter/setter,该属性是通过访问修饰符的存在来定义的。