Groovy runtime method interception
-
30-06-2021 - |
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.
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