class Box {
Closure click
Box () {
click = {}
}
void onClick() {
click()
}
}
class TextBox extends Box {
List<String> content
TextBox (String[] a) {
super()
content = a
}
}
class Main {
public static void main(String[] args) {
Main m = new Main()
}
Main() {
String[] a = ["Hello world!"]
Box b = new TextBox(a)
b.click = {content.add("You clicked this box!")}
b.onClick() //throws Exception
}
}
(上面显然是一个简化;实际上,这些类涉及的更多,调用onClick()是因为点击JFrame)
现在,当我尝试运行它(即运行Main.main())时,我得到一个异常: 在线程“AWT-EventQueue-0”中的异常groovy.lang.MissingPropertyException:没有这样的属性:类的内容:Main
显然,出于某种原因,它是在Main中搜索List,而不是在TextBox或Box中搜索它的位置。我也试过使用这个,所有者和代表,但他们都指向Main。 我设法让它成为一个论点:
...
void onClick() {
click(this)
}
...
b.click = {it.content.add("You clicked this box!")}
然而,实际上需要将“this”传递给闭包只是因为它能够知道从哪里调用它,这似乎很奇怪。难道没有更优雅的解决方案吗?此外,即使确实无法进入TextBox范围,是否有可能进入Box-scope?
答案 0 :(得分:1)
请参阅closures groovy文档。注意隐式变量:this,owner和delegate。
的修改:
在通话前修复委托:
b.click = {content.add("You clicked this box!")}
b.click.delegate = b
答案 1 :(得分:1)
Main() {
String[] a = ["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 the closure is now defined inside Main(),
//Main becomes the delegate. Reset the delegate to TextBox.
b.click.delegate = b
println "3:- $b.click.delegate" //Will print TextBox
content.add("You clicked this box!")
}
println "4:- $b.click.delegate" //Will print Main
b.onClick()
println b.content //Will print [Hello world!, You clicked this box!]
}
//Output:
1:- TextBox@c166770
4:- Main@6dbdc863
2:- Main@6dbdc863
3:- TextBox@c166770
[Hello world!, You clicked this box!]
注意事项:
TextBox
但序列4打印Main
。请注意,到目前为止,delegate
已从b.click
更改为TextBox
之后更改Main
。为了简化操作,您可以将Main
修改为
onClick()
中的内容。
void onClick() {
click.delegate = this
click()
}
有关详细信息,请参阅this script。