是否在Groovy中自动定义了访问器/ mutator?

时间:2013-11-20 07:35:17

标签: groovy

在使用 Groovy In Action 的Groovy处理Java Bean的部分中,我找到了这个脚本(略有修改):

class Book{
  String title
}
def groovyBook = new Book()
// explicit way
groovyBook.setTitle('What the heck, really ?')
println groovyBook.getTitle()
// short-hand way
groovyBook.title = 'I am so confused'
println groovyBook.title  

班级Book中没有这样的方法,那么它是如何工作的?

3 个答案:

答案 0 :(得分:4)

是的,它们是自动定义的,并且调用book.title实际上正在调用book.getTitle()

请参阅http://groovy.codehaus.org/Groovy+Beans

您可以使用以下脚本查看此操作:

def debug( clazz ) {
    println '----'
    clazz.metaClass.methods.findAll { it.name.endsWith( 'Name' ) || it.name.endsWith( 'Age' ) }.each { println it }
}

class A {
    String name
    int age
}
debug( A )
// Prints
// public int A.getAge()
// public java.lang.String A.getName()
// public void A.setAge(int)
// public void A.setName(java.lang.String)

// Make name final
class B {
    final String name
    int age
}
debug( B )
// Prints
// public int B.getAge()
// public java.lang.String B.getName()
// public void B.setAge(int)

// Make name private
class C {
    private String name
    int age
}
debug( C )
// Prints
// public int C.getAge()
// public void C.setAge(int)

// Try protected
class D {
    protected String name
    int age
}
debug( D )
// Prints
// public int D.getAge()
// public void D.setAge(int)

// And public?
class E {
    public String name
    int age
}
debug( E )
// Prints
// public int E.getAge()
// public void E.setAge(int)

答案 1 :(得分:1)

几点说明:

  1. 对于所有属性字段(仅限公共字段),都有自动生成的加法器。
  2. 默认可见性是公开的。因此,您应该使用private / protected关键字来限制访问者生成。
  3. 在访问者内部有直接的字段访问权限。像this.@title
  4. 在构造函数内部,您可以直接访问!这可能是意料之外的。
  5. 对于布尔值,有两个带有isget前缀的getter。
  6. 每个带有这些前缀的方法,甚至是java的方法都被视为访问器,并且可以使用短语法在groovy中引用。
  7. 但有时候,如果你有不明确的召唤,可能会有阶级抛出异常。
  8. 第4点的示例代码。

    class A{
       private int i = 0;
       A(){
         i = 4
         println("Constructor has direct access. i = $i")
       }
       void setI(int val) { i = val; println("i is set to $i"); } 
       int getI(){i}
      }
    
    def a = new A() // Constructor has direct access. i = 4
    a.i = 5 // i is set to 5
    println a.i // 5
    

    第4个音符很重要,如果你在访问器中有一些逻辑,并希望每次调用时都应用它。所以在构造函数中你应该显式调用setI()方法!

    7

    的例子
    class A{
       private int i = 0;
       void setI(String val) { println("String version.")}
       void setI(int val) { i = val; println("i is set to $i"); } 
    }
    
    def a = new A()
    a.i = 5 // i is set to 5
    a.i = "1s5" // GroovyCastException: Cannot cast object '1s5' with class 'java.lang.String' to class 'int'
    

    因此,我看到类似属性的访问使用第一个声明的访问器,并且不支持重载。也许稍后会修复。

答案 2 :(得分:0)

当且仅当不存在访问修饰符时,Groovy才会为字段生成公共访问器/ mutator方法。对于声明为public,private或protected的字段,将不会创建任何getter和setter。

对于声明为final的字段,只会创建访问者。

所有这些都类似地适用于静态字段。