O'Reilly logo

Groovy: Grundlagen und fortgeschrittene Techniken by Joachim Baumann

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

225
6 Closures
In diesem Kapitel beschäftigen wir uns mit Closures, Methoden erster
Ordnung. Diese haben wir bereits in Abschnitt 4.1.3 informell ken-
nengelernt, wir werden unser bisheriges Wissen nochmals kurz zusam-
menfassen.
Wir werden uns detaillierter mit der Erzeugung und dem Aufruf
von Closures beschäftigen, Parameterarten betrachen und genauer
untersuchen, wie Groovy Closures tatsächlich realisiert.
Ein wichtiger Aspekt dieses Kapitels ist der Kontext einer Closure
und damit die Sichtbarkeit von Variablen, Methoden und Attributen
innerhalb der Closure.
Danach werden wir uns mit Currying von Closures auseinander-
setzen. Zum Schluss beschäftigen wir uns mit fortgeschrittenen Ein-
satzmöglichkeiten von Closures.
Sie sollten Kapitel 4 gelesen haben, um die Beispiele nachvollzie-
hen zu können.
6.1 Einführung
Genau genommen ist der Term Closure im Bereich der funktionalen
Sprachen anders belegt als in der Sprache Groovy. Dort bezeichnet
man als Closure oder Funktionsabschluss eine Funktion oder Methode
inklusive des Kontexts, der zu ihrem Definitionszeitpunkt existierte. Es
ist damit also zum Beispiel nicht möglich, eine Closure zu definieren;
wir können sie nur erzeugen, da der jeweilige Kontext ein Teil der Clo-
sure ist. Aber auch an dieser Stelle haben wir streng genommen noch
keine Closure, sondern erst in dem Moment, in dem wir durch einen
Aufruf alle Parameter mit einem Wert versehen.
Groovy sieht das etwas weniger genau. Eine Closure in Groovy ist
zum einen eine Klasse des Systems, von der alle existierenden Closures
abgeleitet sind, auf der anderen Seite auch die einzelnen Instanzen, die
6Closures226
den umgebenden Kontext kapseln und bewahren. Wir betrachten Clo-
sures in Folge genauso pragmatisch wie Groovy.
6.2 Erzeugung einer Closure
Erzeugung einer Closure
In Abschnitt 4.1.3 haben wir Closures bereits kennengelernt und seit-
dem ständig benutzt. Sie sind so allgegenwärtig, dass sie uns gar nicht
auffallen.
Listing 6–1
Die Erzeugung einer
Closure
{ parameter, durch, Komma, getrennt ->
// Quelltext der Closure
}
Zur Erinnerung: Wir erzeugen eine Closure durch eine Folge von
Anweisungen innerhalb zweier geschweifter Klammern. Hierbei kann
nach der öffnenden Klammer optional eine Liste von Parametern fol-
gen, die von den eigentlichen Anweisungen durch die Zeichenfolge
->
getrennt ist. Diese Parameter werden beim Aufruf wie bei einer
Methode mit Werten versorgt, die innerhalb der Closure verwendet
werden können.
Falls keine expliziten Parameter verwendet werden, fällt auch
diese Zeichenfolge weg. Damit stehen die Anweisungen direkt zwi-
schen den Klammern.
Aber auch in diesem Fall gibt es einen impliziten Parameter, auf
den innerhalb der Anweisungen Bezug genommen werden kann. Die-
ser implizite Parameter hat den Namen
it.
Wichtig hierbei ist, dass die Closure durch die Erzeugung nicht
ausgeführt wird. Ohne expliziten Aufruf wird also die entsprechende
Folge von Anweisungen niemals durchlaufen werden.
Referenz auf eine Closure
Wir erhalten eine Referenz auf eine ansonsten namenlose Folge
von Anweisungen, die wir Variablen zuweisen können, als Parameter
in Methodenaufrufen verwenden können oder aber aufrufen können.
Beispiel
In Listing 6–2 erzeugen wir eine Closure, die den ihr übergebenen
Parameter ausgibt und weisen die Referenz einer Variablen
closure
zu
.
Listing 6–2
Verwendung von
Closure-Referenzen
package de.groovybuch.kap6
def closure = { parameter ->
println parameter
}
[1, 2, 3].each(closure)
[1, 2, 3].each closure
[1, 2, 3].each { parameter ->
println parameter
}
2276.3 Aufruf von Closures
Wir verwenden die Methode each() einer Liste, der wir die Referenz
auf die Closure als Argument übergeben
. Im nächsten Aufruf lassen
wir die umgebenden Klammern weg, die bei Methodenaufrufen in
Groovy optional sind
. Im dritten Schritt verwenden wir eine neue,
anonyme Closure anstelle der Referenz in der Variablen
closure .
Diese ist natürlich äquivalent zu der vorherigen Zeile, stellt aber jetzt
die Art der Verwendung dar, die wir schon so gut kennen.
In jedem dieser Fälle wird, trotz der unterschiedlichen Schreib-
weise, eine Referenz auf die Closure an die Methode
each() übergeben,
welche dann in Folge die Closure aufruft.
6.3 Aufruf von Closures
Wir können Closures nicht nur von Methoden aufrufen lassen, die uns
von Groovy zur Verfügung gestellt werden. Wir können dies genauso
gut selber tun.
Auch das haben wir schon gemacht. Wir verwenden einfach die
Referenz auf die Closure und hängen eine öffnende und eine schlie-
ßende Klammer an. Argumente übergeben wir zwischen diesen Klam-
mern. Da die Erzeugung einer Closure eine Referenz zurückliefert,
können wir prinzipiell die Klammern auch direkt hieran anhängen.
Wenn wir die Referenz in einer Variablen halten und einen Aufruf
durchführen, dann sieht dieser exakt aus wie ein normaler Methoden-
aufruf.
Wie funktioniert dies? Groovy interpretiert die öffnende und
schließende Klammer als unseren Versuch, auf der Referenz einen Clo-
sure-Aufruf durchzuführen, und bildet dies ab auf die Methode
call(),
die vom Typ Closure angeboten wird.
Dies bedeutet natürlich, dass auch wir genauso gut die Methode
call() verwenden können, wenn wir es denn wollen. Von Groovy aus
wird dies in den meisten Fällen keinen Sinn haben, aber von Java aus
kann es natürlich sehr interessant sein.
Beispiel
Im Beispiel in Listing 6–3 rufen wir zuerst eine anonym erzeugte
Closure mit dem Argument 2 auf
und geben das in der Variablen res
gespeicherte Resultat aus.
Listing 6–3
Aufruf einer Closure
package de.groovybuch.kap6
res = { x -> x * x }(2)
println res
def quadrat = { x -> x * x }
println quadrat(3)
println quadrat.call(4)

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required