Groovy Closures:这个,所有者,代表让我们制作一个DSL

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值