3

First look at the following Groovy code:

class Car {

    def check() { System.out.println "check called..." }

    def start() { System.out.println "start called..." }

}

Car.metaClass.invokeMethod = { String name, args ->

    System.out.print("Call to $name intercepted... ")

    if (name != 'check') {
        System.out.print("running filter... ")
        Car.metaClass.getMetaMethod('check').invoke(delegate, null)
    }

    def validMethod = Car.metaClass.getMetaMethod(name, args)
    if (validMethod != null) {
        validMethod.invoke(delegate, args)
    } else {
        Car.metaClass.invokeMissingMethod(delegate, name, args)
    }
}

car = new Car()
car.start()

The output is:

Call to start intercepted... running filter... check called...
start called...

According to the Groovy method dispatching mechanism I think the start method in the Car should be called directly instead of being intercepted by the invokeMethod in the Car's metaClass. Why is the start method intercepted by the invokeMethod? How is the invokeMethod invoked when a method is called on an object?

If you can give me some detailed explanations about Groovy method dispatching mechanism(MOP) I will appreciate that.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Samuel Gong
  • 157
  • 1
  • 1
  • 7

1 Answers1

4

In short you are not using the standard meta class, so you don't get the standard Groovy MOP.

Car.metaClass.invokeMethod = { will let Car have an ExpandoMetaClass as meta class. This meta class uses the invokeMethod you give in as open block (like you do) to intercept calls. This is very different from defining an invokeMethod in the class itself.

blackdrag
  • 6,413
  • 2
  • 26
  • 38
  • Could you please explain more about how ExpandoMetaClass change the standard Groovy MOP?@blackdrag – Samuel Gong Jun 15 '15 at 07:28
  • It would be better to ask a specific question and then to answer to that. In genral EMC (ExpandoMetaClass) behaves almost the same as the normal meta class (MetaClassImpl), but it allows adding methods and properties, which the standard one does not. One difference is that a modified EMC (you added a method for example) cannot be automatically removed anymore. As for why this syntax was chosen to intercept calls... I cannot really answer that. That's something you would have to ask Graeme Rocher for example – blackdrag Jun 16 '15 at 07:59
  • Thanks a lot, @blackdrag – Samuel Gong Jun 17 '15 at 11:05