Programming Grails - Cdn.oreilly.com
Programming Grails - Cdn.oreilly.com
Programming Grails - Cdn.oreilly.com
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
Every Groovy class implements the groovy.lang.GroovyObject interface (it’s added<br />
by the <strong>com</strong>piler) that includes these methods:<br />
Object invokeMethod(String name, Object args)<br />
Object getProperty(String property)<br />
void setProperty(String property, Object newValue)<br />
MetaClass getMetaClass()<br />
void setMetaClass(MetaClass metaClass)<br />
Java classes can also implement GroovyObject to add Groovy-like<br />
behavior. The most convenient approach for this is to subclass the<br />
groovy.lang.GroovyObjectSupport adapter class, which implements<br />
the interface and provides sensible default implementations of the<br />
methods that can be overridden as needed.<br />
When you invoke a method in Groovy (including accessing a property, because that<br />
calls the corresponding getter method), it’s actually dispatched to the object’s metaclass.<br />
This provides an AOP-like interception layer. The calls are implemented with reflection,<br />
which is slower than direct method invocation. But each new release of Java adds re‐<br />
flection speed improvements, and Groovy has several optimizations to reduce the cost<br />
of this overhead, the most significant being call site caching. Early versions of Groovy<br />
were quite slow, but modern Groovy has seen huge performance boosts and is often<br />
nearly as fast as Java. And because network latency and database access tend to con‐<br />
tribute most to total web request time, the small increase in invocation time that Groovy<br />
can add tends to be insignificant, because it’s such a small percentage of the total time.<br />
Adding Methods<br />
The syntax for adding a method at runtime is essentially just one that registers a closure<br />
in the metaclass that’s associated with the specified method name and signature:<br />
List.metaClass.removeRight = { int index -><br />
delegate.remove(delegate.size() - 1 - index)<br />
}<br />
The List interface has a remove method, but this addition removes the item considering<br />
the position from the right instead of the left like remove:<br />
assert 3 == [1, 2, 3].removeRight(0)<br />
assert 2 == [1, 2, 3].removeRight(1)<br />
assert 1 == [1, 2, 3].removeRight(2)<br />
Recall that closures have a delegate that handles method calls invoked inside the closure.<br />
When adding methods to the metaclass, you can access the instance in which closure<br />
is invoked with the delegate property; in this example, it’s the list instance that remove<br />
Right is called on.<br />
22 | Chapter 1: Introduction to Groovy