04.07.2013 Views

Programming Grails - Cdn.oreilly.com

Programming Grails - Cdn.oreilly.com

Programming Grails - Cdn.oreilly.com

SHOW MORE
SHOW LESS

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

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!