Closure (česky uzávěry) umožňují uvnitř nich volat metody. Příklad:
class SomeClass {
void callClosure() {
def dog = {
woof() // volání metody void woof() z closure
}
dog() // zavolá closure
}
void woof() {
println "Woof!"
}
}
Každý closure má obsažené 3 různé atributy: Owner, Delegate a this. this odkazuje na instanci třídy, kde je closure definován. Owner obsahuje odkaz na instanci, kde je obsažen closure. Ve většině případů je tedy this stejný jako owner. Výjimkou je třeba tento případ (z knihy Programming Groovy):
examiningClosure() {Výstup:
println "In First Closure:"
println "class is " + getClass().name
println "this is " + this + ", super:" + this.getClass().superclass.name // this = owner
println "owner is " + owner + ", super:" + owner.getClass().superclass.name
println "delegate is " + delegate +
", super:" + delegate.getClass().superclass.name
examiningClosure() { // closure uvnitř closure
println "In Closure within the First Closure:"
println "class is " + getClass().name
println "this is " + this + ", super:" + this.getClass().superclass.name // this != owner
println "owner is " + owner + ", super:" + owner.getClass().superclass.name
println "delegate is " + delegate +
", super:" + delegate.getClass().superclass.name
}
}
In First Closure:
class is ThisOwnerDelegate$_run_closure1
this is ThisOwnerDelegate@55e6cb2a, super:groovy.lang.Script
owner is ThisOwnerDelegate@55e6cb2a, super:groovy.lang.Script
delegate is ThisOwnerDelegate@55e6cb2a, super:groovy.lang.Script
In Closure within the First Closure:
class is ThisOwnerDelegate$_run_closure1_closure2
this is ThisOwnerDelegate@55e6cb2a, super:groovy.lang.Script
owner is ThisOwnerDelegate$_run_closure1@15c330aa, super:groovy.lang.Closure
delegate is ThisOwnerDelegate$_run_closure1@15c330aa, super:groovy.lang.Closure
Atribut Delegate v closure je ten, který právě umožňuje dělat kouzla jako v static mapping = {}. Closure totiž umožňuje nastavit atribut Delegate na jiný objekt pomocí setDelegate(Object delegate) a pak volat jejich metody. V praxi to znamená toto:
Doménová třída s defaultním řazením entit podle dne:
class Attendance {V doménové třídě však žádná metoda sort defaultně neexistuje. Avšak třída je platná a funkční. Pokud použijete debugger a zastavíte zpracování v closure mappings, uvidíte následující:
Date day
static mapping = {
sort("day")
}
}
this = class wellness.AttendanceKdyž si otevřete třídu HibernateMappingBuilder, nacházejí se tam metody, které se používají v mapping, jako je výše zmíněný sort, cache, table, version apod. To je celé tajemství.
owner = class wellness.Attendance
delegate = org.codehaus.groovy.grails.orm.hibernate.cfg.HibernateMappingBuilder@3321875 // ha, to je on
P.S. Další otázkou je, kde je nastaven setDelegate() v doménových třídách? To jsem se ještě nedočetl (ale myslím, že je to udělané pomocí MOP). O tom napíšu, až budu vědět na stopro nebo si to někde přečtu.
Žádné komentáře:
Okomentovat