04.07.2013 Views

Programming Grails - Cdn.oreilly.com

Programming Grails - Cdn.oreilly.com

Programming Grails - Cdn.oreilly.com

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

println hello.getClass().superclass.name<br />

The class itself will have a name like ConsoleScript14$_run_closure1. Nested closures<br />

extend this naming convention; for example, if you look in the classes directory of a<br />

<strong>Grails</strong> application, you’ll see names like BuildConfig$_run_closure1_closure2.class,<br />

which are the result of having repositories, dependencies, and plugins closures de‐<br />

fined within the top-level grails.project.dependency.resolution closure.<br />

The dollar sign in the class and filename will look familiar if you’ve used anonymous<br />

inner classes before. In fact, that’s how they’re implemented. They’re different from<br />

anonymous inner classes in that they can access nonfinal variables outside of their scope.<br />

This is the “close” part of closure—they enclose their scope, making all of the variables<br />

in the scope the closure is in available inside the closure. This can be emulated by an<br />

inner class by using a final variable with mutable state, although it’s cumbersome. For<br />

example, this Java code doesn’t <strong>com</strong>pile, because i isn’t final, and making it final defeats<br />

the purpose, because it needs to be changed inside the onClick method:<br />

interface Clickable {<br />

void onClick()<br />

}<br />

int i = 0;<br />

Clickable c = new Clickable() {<br />

public void onClick() {<br />

System.out.println("i: " + i);<br />

i++;<br />

}<br />

};<br />

We can fix it with a final 1-element array (because the array values are still mutable):<br />

final int[] i = { 0 };<br />

Clickable c = new Clickable() {<br />

public void onClick() {<br />

System.out.println("i: " + i[0]);<br />

i[0]++;<br />

}<br />

};<br />

but it’s an unnatural coding approach. The Groovy equivalent with a closure is a lot<br />

cleaner:<br />

int i = 0<br />

def c = { -><br />

println "i: $i"<br />

i++<br />

} as Clickable<br />

So how does Groovy break this JVM rule that anonymous inner classes can’t access<br />

nonfinal variables? It doesn’t—it uses a trick like the one above. Instead of using arrays<br />

like the above example, there’s a holder class, groovy.lang.Reference. Enclosed vari‐<br />

10 | Chapter 1: Introduction to Groovy

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

Saved successfully!

Ooh no, something went wrong!