2012-04-18 72 views
0

如何避免將函數作爲參數傳遞給類構造函數時的閉包?斯卡拉 - 如何避免關閉?

我的類構造函數接受() => Unit類型的函數。在程序的工作過程中,我想從一個可變的地圖訪問一個鍵值對,當美妙的對象觸發時未與構造函數創建對象的時刻定義

val cats = scala.collection.mutable.Map[String, Cat] 

class Trigger(period: Long, f:() => Unit) { 

    //pseudocode: 
    when period passes, f() 

} 

someWonderfulObject += new Trigger (1000,() => cats("Hershy").meow) 

cats += ("Hershy" -> Cat()) 

,然後,它的觸發器,我得到的錯誤是沒有像「Hershy」這樣的鍵。我的結論很明顯,這是由於f傳遞給Trigger的缺陷在沒有「Hershy」的狀態下被關閉。

我的問題是現在 - 如何避免Scala在這裏使用閉包,而是看看cats的實際狀態?

UPDATE:

守則 「時期間通過」 是這樣的:

def update(tpf: Float) { 
    timePassed += tpf 
    if(timePassed > period) f() 
} 

tpf值來自上面,所以在這裏這一切似乎確定。

UPDATE:

我已經發現在另一個問題,完全無關的地方,我都困惑的這些東西的容器。不過,謝謝大家,我從答案中學到了一些東西。

+1

你的貓是一個'val',持有一個可變收藏的參考。閉包不會克隆你的對象,它理論上唯一能做的就是複製'cats'(一個引用)的值。但是因爲「貓」是一個「val」,換句話說就是一個常數,所以這不是問題的根源。 – 2012-04-18 10:46:27

+1

順便說一句,這怎麼編譯:'(「Hershy」 - > Cat)'? 「貓」是一類,它本身不是「貓」。我想這只是僞代碼 - 當其他人試圖調試他們從未見過的代碼時,它總是困惑不解。 – 2012-04-18 10:48:50

+0

哦,對不起,它的意思是貓() – noncom 2012-04-18 11:17:53

回答

6

封閉不會做這樣的事情(這將很難指定,有可怕的表現,並使整個事情無用)。閉包可能包含對貓的引用,或者包含對貓的實例,而不是副本。

此代碼按預期工作:

val cats = collection.mutable.Map[String, String]() 

class Trigger(name: String, f:() => Unit) { 
    def fire = { 
    println("Fire " + name) 
    f() 
    } 
} 

val trigger = new Trigger("calling Hershy",() => println(cats("Hershy"))) 
cats += "Hershy" -> "meow" 
trigger.fire // prints Fire calling Hershy 

關閉是沒有過錯的,我懷疑這是不會出現你的樣品中的東西。

+1

很好的例子,但永遠不會忘記那隻貓「喵喵」;-)你忘了那個關鍵的一點,除了印製「Fire Hershy」之外,它還印着「喵」的字樣。如果沒有「喵喵」,你的答案就不會是封閉式的簡單例子,它是...... – virtualeyes 2012-04-18 11:21:49