Skip to content
Closure Delegation
step 1/5

Reading — step 1 of 5

Learn

~1 min readClosures and Builders

Groovy closures have three contexts for resolving names:

  • owner — the enclosing scope (where the closure was defined)
  • delegate — a configurable target (default: same as owner)
  • this — the enclosing class

This is what makes Gradle's task { ... } style work — the closure's delegate is set to the task being configured, so methods like dependsOn resolve against it.

class Person {
    String name
    int age
}

def configure(closure) {
    def p = new Person()
    closure.delegate = p
    closure.resolveStrategy = Closure.DELEGATE_FIRST
    closure.call()
    return p
}

def ada = configure {
    name = "Ada"        // sets p.name (delegate-first)
    age = 36
}

println ada.name        // "Ada"

Resolve strategies:

  • Closure.OWNER_FIRST (default) — owner scope wins
  • Closure.DELEGATE_FIRST — delegate wins
  • Closure.OWNER_ONLY / DELEGATE_ONLY

Pattern: builders. A builder method takes a closure, sets its delegate, and runs it:

def html(@DelegatesTo(HtmlBuilder) Closure body) {
    new HtmlBuilder().with(body)
}

html {
    title "Hello"
    body {
        p "World"
    }
}

Gradle, MarkupBuilder, JsonBuilder all use this pattern.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…