user872831
user872831

Reputation: 101

Set delegate of a MethodClosure in Groovy

I am experimenting with Groovy closures and delegates right now. I have the following code setting the delegate of a closure to another class, which works perfectly fine.

def closure = {
    newMethod()
};
closure.setDelegate(new MyDelegate());
closure.setResolveStrategy(Closure.DELEGATE_ONLY);
closure();

class MyDelegate {
    public void newMethod() {
        println "new Method";
    }
}

This prints out "new Method", showing that newMethod() in MyDelegate is actually called. Now I am trying to do the same with MethodClosure.

public class TestClass {
    public void method() {
        newMethod();
    }
}

TestClass a = new TestClass();
def methodClosure = a.&method;
methodClosure.setDelegate(new MyDelegate());
methodClosure.setResolveStrategy(Closure.DELEGATE_ONLY);
methodClosure();

class MyDelegate {
    public void newMethod() {
        println "new Method";
    }
}

However, this time, I get the following exception: Exception in thread "main" groovy.lang.MissingMethodException: No signature of method: TestClass.newMethod() is applicable for argument types: () values: [].

So for this methodClosure, it doesn't seem like it's going to the delegate for method lookup at all. I have a feeling this is probably intended behavior, but are there ways to actually use delegates for MethodClosures?

Thanks alot.

Upvotes: 3

Views: 1421

Answers (1)

ataylor
ataylor

Reputation: 66109

MethodClosures are actually just adapters for calling methods with through the Closure interface. It doesn't do delegation, as you've seen.

One way to use MyDelegate as a delegate would be to mix it in, like so:

TestClass a = new TestClass()
a.metaClass.mixin MyDelegate
def methodClosure = a.&method
methodClosure()

// or skip the closure altogether
TestClass b = new TestClass()
b.metaClass.mixin MyDelegate
b.method()

Upvotes: 2

Related Questions