2013-05-21 54 views
0
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點擊)如何獲取Groovy中從中調用閉包的類(範圍)?

現在,當我嘗試運行Main.main()),我得到一個異常: 線程「AWT-EventQueue-0」中的異常groovy.lang.MissingPropertyException:沒有這樣的屬性:內容類:主要

顯然,出於某種原因,它在Main中搜索列表,而不是在TextBox或Box中,從中調用它。我也嘗試過使用這個,所有者和代表,但他們都指向Main。 我設法把它給予這個作爲參數的工作:

... 
void onClick() { 
    click(this) 
} 
... 
b.click = {it.content.add("You clicked this box!")} 

看來,然而,奇怪的實際需要通過「本」,以將閉合它能夠知道它被稱爲只是從。沒有更優雅的解決方案嗎?另外,即使進入TextBox範圍確實不可能,是否有可能進入Box範圍?

回答

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:- [email protected] 
4:- [email protected] 
2:- [email protected] 
3:- [email protected] 
[Hello world!, You clicked this box!] 

注意要點:

  • 序列4是本圖2和3之前,因爲封閉件不叫/調用在那個時間點。
  • 序列1打印TextBox但序列4打印Main。請注意,到目前爲止,delegate已經從TextBox更改爲Main(在定義關閉b.click之後)。

爲了使事情變得更容易,而不是Main改變的東西,你可以修改onClick()作爲

void onClick() { 
    click.delegate = this 
    click() 
} 

,詳見this script

+0

嗯,好的。這確實比使用「它」更優雅。雖然我仍然需要通過「this」(click.delegate = this),但是我認爲如果不這樣做,那就是不可能的。非常感謝! – Callid

+0

Yw。如果你沒有正確地設置委託,這是不可能的,這就是封閉性質。此外,我們沒有通過任何關閉,我們正在設置其代表財產。 :)(堅持封閉使用父代替被調用者)。 – dmahapatro

1

請參閱closures groovy文檔。注意隱式變量:this,owner和delegate。
編輯:呼叫之前 修復委託:

b.click = {content.add("You clicked this box!")} 
b.click.delegate = b 
+0

正如我所說: 「我也嘗試過使用這個,所有者和代表,但他們都指向Main。」 – Callid

+0

查看編輯答案 –