【问题标题】:What are delegate objects?什么是委托对象?
【发布时间】:2016-08-21 18:54:51
【问题描述】:

我目前正在编写 gradle 构建脚本。什么是委托对象以及它们何时使用?

class GroovyGreeter {
    String greeting = "Default greeting"
    def printGreeting(){println "Greeting: $greeting"}
}

def myGroovyGreeter = new GroovyGreeter()

myGroovyGreeter.printGreeting()
myGroovyGreeter.greeting = "My custom greeting"
myGroovyGreeter.printGreeting()

/*

The last Groovy feature we'll cover is that closures can have a delegate
object. Any variables or methods referenced in the closure that don't have a
local definition are then evaluated against the closure's delegate. Let's make
a closure that will access the property and method of our GroovyGreeter class.

*/

def greetingClosure = {
    greeting = "Setting the greeting from a closure"
    printGreeting()
}

//greetingClosure() // This doesn't work, because `greeting` isn't defined
greetingClosure.delegate = myGroovyGreeter
greetingClosure() // This works as `greeting` is a property of the delegate

请帮帮我。

【问题讨论】:

标签: android gradle groovy


【解决方案1】:

什么是闭包的委托?

当您将闭包的委托设置为另一个对象时,对在闭包范围内无法解析的属性/方法的任何调用都将由闭包的委托解决。在您的示例中,greetingprintGreetinggreetingClosure 闭包的范围内未定义

def greetingClosure = {
    greeting = "Setting the greeting from a closure"
    printGreeting()
}

所以当你将此闭包的委托设置为GroovyGreeter的实例时

greetingClosure.delegate = myGroovyGreeter

它们被这个对象(成功地)解析了,因为它确实用这些名称定义了一个属性和方法。

什么时候使用委托?

它们通常用于 DSL 或构建器中,当您希望 DSL/构建器的用户能够以任何名称调用方法时,并且在 DSL 中使用的方法名称几乎就像附加的方法参数一样。以下面使用构建器生成 XML 为例

def writer = new StringWriter()
def xml = new MarkupBuilder(writer) 

xml.records() { 
    car(name:'HSV Maloo', make:'Holden', year:2006) {
        country('Australia')
        record(type:'speed', 'Production Pickup Truck with speed of 271kph')
    }
}

def records = new XmlSlurper().parseText(writer.toString())

创建构建器后我们要做的第一件事是调用records 并传递一个闭包参数。实际上,在 MarkupBuilder 中的任何地方都没有定义带有闭包参数的 records 方法,但所有未定义的方法都将使用 Groovy's methodMissing feature 路由到 MarkupBuilder

在传递给records 的闭包中,我们调用了在编译时未定义的各种其他方法,例如carMarkupBuilder 是如何解决这些方法调用的?因为这个闭包的委托被设置为MarkupBuilder实例。

【讨论】:

  • hmm,你给出的例子涉及更多,我可以看到委托被设置在BuilderSupport MarkupBuilder扩展,但records方法是无处可寻。
猜你喜欢
  • 1970-01-01
  • 2020-05-31
  • 1970-01-01
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
  • 2013-12-30
相关资源
最近更新 更多