Groovy闭合非常酷。 为了完全理解它们,我认为了解此信息 , 所有者和委托的含义非常重要。 一般来说:
- this :指的是定义闭包的类的实例。
- owner :与此相同,除非该闭包在另一个闭包内定义,在这种情况下,所有者指的是外部闭包。
- 委托 :与所有者相同。 但是,它是唯一可以通过编程方式更改的控件,并且它使Groovy闭包真正强大。
困惑? 让我们看一些代码。
class MyClass {
def outerClosure = {
println this.class.name // outputs MyClass
println owner.class.name // outputs MyClass
println delegate.class.name //outputs MyClass
def nestedClosure = {
println this.class.name // outputs MyClass
println owner.class.name // outputs MyClass$_closure1
println delegate.class.name // outputs MyClass$_closure1
}
nestedClosure()
}
}
def closure = new MyClass().closure
closure()
关于上述代码:
- 此值始终引用封闭类的实例。
- owner始终与此相同,除了嵌套的闭包。
- 默认情况下, 委托与所有者相同。 可以更改它,我们很快就会看到。
那么,什么是一点来看, 业主 , 委托 ? 记住,闭包不只是匿名函数。 如果它们是我们,我们就可以称它们为Lambdas,而我们不必再想出另一个词,对吗?
闭包超出lambda的地方在于它们绑定或“封闭”在闭包的范围中未明确定义的变量。 再次,让我们看一些代码。
class MyClass {
String myString = "myString1"
def outerClosure = {
println myString; // outputs myString1
def nestedClosure = {
println myString; // outputs myString1
}
nestedClosure()
}
}
MyClass myClass = new MyClass()
def closure = new MyClass().outerClosure
closure()
println myClass.myString
好的,因此闭包和nestedClosure都可以访问在其定义的类的实例上的变量。这很明显。 但是,它们究竟如何解析myString引用? 好吧,就像这样。 如果未在闭包中显式定义变量,则将检查此范围,然后检查所有者范围,然后检查委托范围。 在这个例子中,MyString的是不是无论是在封闭的定义,因此常规检查他们的这种引用,并看到myString的定义存在并使用。 好的,让我们看一个示例,在该示例中,它无法在闭包中找到变量,并且无法在闭包的此范围内找到它,但可以在闭包的所有者范围内找到它。
class MyClass {
def outerClosure = {
def myString = "outerClosure";
def nestedClosure = {
println myString; // outputs outerClosure
}
nestedClosure()
}
}
MyClass myClass = new MyClass()
def closure = new MyClass().closure
closure()
在这种情况下,Groovy在nestedClosure或此范围内找不到myString 。 然后,它检查所有者范围,对于nestedClosure而言 ,该范围是outsideClosure 。 它在那里找到myString并使用它。 现在,让我们看一个示例,其中Groovy在闭包中,或在此或所有者范围内找不到变量,但可以在闭包的委托范围内找到变量。 如前所述,除非明确更改,否则所有者委托范围与所有者范围相同。 因此,为了使它更有趣,让我们更改委托。
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() // outputs: "I am over in here in myOtherClass"
对Groovy中的闭包的词法范围具有如此多的控制权的能力赋予了巨大的力量。 即使设置了委托,也可以将其更改为其他内容,这意味着我们可以使闭包的行为超级动态。
class MyOtherClass {
String myString = "I am over in here in myOtherClass"
}
class MyOtherClass2 {
String myString = "I am over in here in myOtherClass2"
}
class MyClass {
def closure = {
println myString
}
}
MyClass myClass = new MyClass()
def closure = new MyClass().closure
closure.delegate = new MyOtherClass()
closure() // outputs: I am over in here in myOtherClass
closure = new MyClass().closure
closure.delegate = new MyOtherClass2()
closure() // outputs: I am over in here in myOtherClass2
好的,因此现在应该更清楚此 所有者和委托人实际对应的内容。 如前所述,将首先检查闭包本身,然后检查闭包的此范围,而不是闭包的所有者 ,然后是其委托 。 但是,Groovy非常灵活,可以更改此策略。 每个闭包都具有一个称为resolveStrategy的属性。 可以设置为:
- 关闭.OWNER_FIRST
- 关闭.DELEGATE_FIRST
- 关闭.OWNER_ONLY
- 关闭。DELEGATE_ONLY
因此,在哪里可以很好地利用委托属性的动态设置。 好吧,您可以在GORM for Grails中看到。 假设我们具有以下域类:
class Author {
String name
static constraints = {
name size: 10..15
}
}
在Author类中,我们可以看到使用看起来像DSL的方式定义的约束,而在Java / Hibernate世界中,我们将无法编写具有表现力的DSL,而是使用注释(它比XML更好,但仍不如DSL)。 那么,为什么我们可以在Groovy中使用DSL? 嗯,这是因为对闭包的功能委托设置增加了Groovy的元编程工具箱。 在Author GORM对象中, 约束是一个闭包,它使用一个名称大小为10到15的值的参数来调用名称方法。它也可以写为更少的DSL'y:
class Author {
String name
static constraints = {
name(size: 10..15)
}
}
无论哪种方式,Grails都会在后台寻找约束关闭并将其委托分配给综合约束逻辑的特殊对象。 在伪代码中,将是这样的……
// Set the constraints delegate
constraints.delegate = new ConstraintsBuilder(); // delegate is assigned before the closure is executed.
class ConstraintsBuilder = {
//
// ...
// In every Groovy object methodMissing() is invoked when a method that does not exist on the object is invoked
// In this case, there is no name() method so methodMissing will be invoked.
// ...
def methodMissing(String methodName, args) {
// We can get the name variable here from the method name
// We can get that size is 10..15 from the args
...
// Go and do stuff with hibernate to enforce constraints
}
}
所以你有它。 闭包非常强大,它们可以委派给可以在运行时动态设置的对象。 这在Groovy的元编程功能中起着重要作用,这意味着Groovy可以具有一些非常有表现力的DSL。
翻译自: https://www.javacodegeeks.com/2014/05/groovy-closures-this-owner-delegate-lets-make-a-dsl.html