Calling closure on different object?

2019-02-19 23:59发布

问题:

Suppose I have this class:

class MyClass {
    int myInt

    MyClass(myInt) {
        this.myInt = myInt
    }

    def myMethod() {
        print this.myInt
    }
}

And somewhere I have:

def myClass1 = new MyClass(1)
def myMethodClosure = myClass1.&myMethod
def myClass2 = new MyClass(2)

Now if I call myMethodClosure() it will call myMethod() on myClass1 instance which will print 1. What I want is to call the same myMethodClosure but on a different instance, in this case on myClass2 so it can print 2. Is this possible?

I have tried using setDelegate(), but it does not work. I have also seen that there is field thisObject inside the closure class, but it does not have a setter, only a getter.

回答1:

There were two methods added to Groovy to aid serialization of Closures, dehydrate and rehydrate. Basically, they strip (and reconstruct) a Closure's owner, thisObject and delegate. In this example, you could do:

myMethodClosure.rehydrate( myClass2, myClass2, myClass2 )()

To get the output 2, however I'd be wary about doing this as it is not what the method was intended for and there could be serious unforeseen consequences.

A better solution would probably be to write a factory method that gets a method reference for the given instance of MyClass. There may be other -- better -- solutions, but it depends on the situation you are in (that I suspect is not shown by the example in the question)



回答2:

I believe closure "includes" the enclosing object to act upon. It is not possible override "this" inside a closure at runtime.