4

I've noticed some strange behavior with the Groovy MetaClass and I'm wondering if anyone can give me a clue to what's happening here.

This works fine:

@Override
Object invokeMethod(String name, Object args) {
    if(true) {
        println("Should only see this once")
        def impl = { Object theArgs -> println("Firing WeirdAction") }
        getMetaClass()."$name" = impl
        return impl(args)
    }
}

However if I take off the if statement it throws a MissingPropertyException:

@Override
Object invokeMethod(String name, Object args) {
    println("Should only see this once")
    def impl = { Object theArgs -> println("Firing WeirdAction") }
    getMetaClass()."$name" = impl
    return impl(args)
}

Here's my class instantiation and call, the class is empty except for the above method definition.

IfTester sut = new IfTester()
sut.WeirdAction()

Anyone have an idea what I'm misunderstanding here?

gt124
  • 1,238
  • 13
  • 23

1 Answers1

1

Using Groovy 2.4.5, the issue appears to be related to getMetaClass() versus IfTester.getMetaClass(). Consider:

class IfTester {

    @Override
    Object invokeMethod(String name, Object args) {
        if (true) {
        println "Should only see this once"
        def impl = { def theArgs -> println "Firing WeirdAction" }
        def mc1 = getMetaClass()
        println "mc1: " + mc1
        println "----"
        def mc2 = IfTester.getMetaClass()
        println "mc2: " + mc2
        IfTester.getMetaClass()."$name" = impl
        return impl(args)
        }
    }
} 

IfTester sut = new IfTester()
sut.WeirdAction()

With the if(true), then mc1 and mc2 are identical, and both work. Without the if, mc1 is different and using that style causes the error.

I don't know the root cause, nor if it is a bug. Somehow, it seems that there is a scoping issue or that the sense of this is different in that context.

Michael Easter
  • 23,733
  • 7
  • 76
  • 107
  • Running your example and noticing the different returns between the class call and the instance call, I googled again and found a similar thread https://stackoverflow.com/questions/34449587/groovy-this-metaclass-versus-instance-metaclass . It's strange to me that the scope is changing the call from instance to class but maybe I'm not completely getting it at this point. – gt124 Aug 26 '16 at 02:45