Question

I'm playing with Groovy and I wonder, why doesn't this piece of code works?

package test

interface A {
    void myMethod()
}

class B implements A {
    void myMethod() {
        println "No catch"
    }
}

B.metaClass.myMethod = {
    println "Catch!"
}

(new B()).myMethod()

It prints out No catch, while I expect it to print Catch! instead.

Was it helpful?

Solution

It's a bug in Groovy, there is an open issue in JIRA: Cannot override methods via metaclass that are part of an interface implementation, GROOVY-3493.

OTHER TIPS

Instead of rewriting B.metaClass.myMethod, try following:

 B.metaClass.invokeMethod = {String methodName, args ->
    println "Catch!"
 }

This blog post describes it quite well.

There is a workaround but it only applies to all classes and not specific instances.

metaclass modification BEFORE construction:

interface I {
    def doIt()
}

class T implements I {
    def doIt() { true }
}

I.metaClass.doIt = { -> false }
T t = new T()
assert !t.doIt()

metaclass modification AFTER construction:

interface I {
    def doIt()
}

class T implements I {
    def doIt() { true }
}

T t = new T()
// Removing either of the following two lines breaks this
I.metaClass.doIt = { -> false }
t.metaClass.doIt = { -> false }
assert !t.doIt()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top