Answer to the Question
When a Closure is invoked, Groovy decides where to look for a method or property based on the resolveStrategy of that closure. The default strategy is OWNER_FIRST, which means:
- First look on the owner (the object that created the closure).
- If the method/property isn’t found, look on the delegate.
So, if both the owner and the delegate expose a method with the same name, the call is dispatched to the owner’s implementation unless the strategy is changed to DELEGATE_FIRST or another strategy that prioritises the delegate.
Constraints on Changing Owner vs. Delegate
The delegate is designed to be mutable. You can reassign it at any time:
myClosure.delegate = newObj
This change will affect all subsequent invocations of the closure.
The owner is also technically settable via setOwner(), but it is treated as the "enclosing" context of the closure. In practice:
- Changing the owner after the closure has been created is possible but discouraged.
- It can break references to local variables, inner classes, and the closure’s lexical scope.
- Some Groovy implementations treat the owner as effectively read‑only; attempting to change it may throw an exception or be ignored.
- If you do change the owner, you must also be careful with the
resolveStrategy, because the closure may still resolve to the original owner’s bindings until the strategy is updated.
In short, delegate changes are safe and common in DSLs, while owner changes are a last‑resort and can lead to subtle bugs.
Practical Verification Steps
Print the current owner and delegate to confirm expectations:
println "Owner: ${myClosure.owner}"
println "Delegate: ${myClosure.delegate}"
Change the delegate and test a method call that exists on both objects:
myClosure.delegate = delegateObj
myClosure.resolveStrategy = Closure.DELEGATE_FIRST
myClosure.someMethod()
Attempt to change the owner (if your Groovy version allows it) and observe whether the change takes effect:
myClosure.owner = newOwner
myClosure.resolveStrategy = Closure.OWNER_FIRST
myClosure.someMethod()
Run the same test on the exact Groovy version you’re using; behaviour can differ between 2.x and 3.x.
Missing Diagnostic Detail Needed
Could you let me know which Groovy version you’re running? The resolution order and mutability of owner can differ between 2.x and 3.x releases.