Groovy 闭包:this、owner、delegate 让我们创建一个领域特定语言(DSL)。

Groovy 闭包非常酷。要完全理解它们,理解thisownerdelegate的含义非常重要。

  • this:指闭包所在类的实例。
  • owner:通常与this相同,除非闭包在另一个闭包内部定义,此时owner指外部闭包。
  • delegate:与owner相同,但它是唯一可以通过编程更改的,这使 Groovy 闭包非常强大。

代码示例:

class MyClass {
    def outerClosure = {
        println this.class.name    // 输出 MyClass
        println owner.class.name    // 输出 MyClass
        println delegate.class.name  // 输出 MyClass
        def nestedClosure = {
            println this.class.name    // 输出 MyClass
            println owner.class.name    // 输出 MyClass$_closure1
            println delegate.class.name  // 输出 MyClass$_closure1
        }
        nestedClosure()
    }
}

def closure = new MyClass().closure
closure()

在上述代码中:

  • this值始终指包含类的实例。
  • owner通常与this相同,除了嵌套闭包。
  • delegate默认与owner相同,可以更改。

闭包不仅仅是匿名函数,它们还能绑定在闭包作用域中未明确定义的变量。例如:

class MyClass {
    String myString = "myString1"
    def outerClosure = {
        println myString;     // 输出 myString1
        def nestedClosure = {
            println myString;  // 输出 myString1
        }
        nestedClosure()
    }
}

MyClass myClass = new MyClass()
def closure = new MyClass().outerClosure
closure()

println myClass.myString 

如果闭包中未定义变量,会依次检查thisownerdelegate作用域。

还可以通过更改delegate来改变闭包的行为,如:

class MyOtherClass {
    String myString = "I am over in here in myOtherClass"
}

class MyClass {
    def closure = {
        println myString
    }
}

MyClass myClass = new MyClass()
def closure = new MyClass().closure
closure.delegate = new MyOtherClass()
closure()   // 输出: "I am over in here in myOtherClass"

每个闭包都有一个resolvedStrategy属性,可以设置为Closure.OWNER_FIRSTClosure.DELEGATE_FIRSTClosure.OWNER_ONLYClosure.DELEGATE_ONLY

在 Grails 的 GORM 中,delegate的动态设置有实际应用,例如在Author类中:

class Author {
    String name 

    static constraints = {
        name size: 10..15
    }
}

通过闭包和delegate的设置,实现了更简洁的 DSL 表达约束。

总之,闭包非常强大,可以动态委托给对象,在 Groovy 的元编程能力中起着重要作用,能实现非常有表现力的 DSL。

阅读 7
0 条评论