How do I get the class (scope) from which a closure is called in Groovy? -
class box { closure click box () { click = {} } void onclick() { click() } } class textbox extends box { list<string> content textbox (string[] a) { super() content = } } class main { public static void main(string[] args) { main m = new main() } main() { string[] = ["hello world!"] box b = new textbox(a) b.click = {content.add("you clicked box!")} b.onclick() //throws exception } } (the above is, obviously, simplification; in reality, classes bit more involved, , calling of onclick() due click on jframe)
now, when try run (i.e. run main.main()), exception: exception in thread "awt-eventqueue-0" groovy.lang.missingpropertyexception: no such property: content class: main
clearly, is, reason, searching list in main, not in textbox or box, called. tried using this, owner , delegate, point main well. managed have work giving argument:
... void onclick() { click(this) } ... b.click = {it.content.add("you clicked box!")} it seems, however, weird need pass "this" closure able know called from. isn't there more elegant solution? also, if indeed impossible textbox-scope, somehow possible box-scope?
main() { string[] = ["hello world!"] box b = new textbox(a) println "1:- $b.click.delegate" //will print textbox b.click = { println "2:- $b.click.delegate" //will print main //since closure defined inside main(), //main becomes delegate. reset delegate textbox. b.click.delegate = b println "3:- $b.click.delegate" //will print textbox content.add("you clicked box!") } println "4:- $b.click.delegate" //will print main b.onclick() println b.content //will print [hello world!, clicked box!] } //output: 1:- textbox@c166770 4:- main@6dbdc863 2:- main@6dbdc863 3:- textbox@c166770 [hello world!, clicked box!] points note:
- sequence 4 present before 2 , 3 since closure not called/invoked @ point of time.
- sequence 1 prints
textboxsequence 4 printsmain. notedelegatehas changed (after defining closureb.click)textboxmainnow.
to make things easier, instead of changing things in main, can modify onclick() as
void onclick() { click.delegate = click() } refer this script details.
Comments
Post a Comment