2012-04-18 2 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"와 같은 키가 없다는 오류가 발생합니다. 결론적으로, 이것은 "Hershy"가 없었던 상태에서 Trigger 죄수 팀에게 제출 된 f이 죄수로 넘어 갔기 때문인 것으로 판단됩니다.

내 질문이 지금입니다 - Scala가 여기에서 클로저를 사용하지 않고 대신 cats의 실제 상태를 보지 못하도록하는 방법은 무엇입니까?

UPDATE : "기간이 경과 할 때"에 대한

코드는 이것이다 :

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

tpf 값은 위에서 온다, 그래서 여기에이 모든 것이 좋아 보인다.

업데이트 : 다른에있을 수있는 문제를 발견

는 전혀 관련이없는 장소, 나는이 모든 것들의 컨테이너를 혼동했다. Howevr, 고맙다. 대답에서 뭔가를 배웠다.

+1

고양이는 가변 컬렉션에 대한 참조를 보유한 'val'입니다. 클로저는 객체를 복제하지 않으며, 이론적으로 할 수있는 유일한 방법은'cats' (참조)의 값을 복사하는 것입니다. 그러나'cat'은'val', 즉 상수이기 때문에 이것은 문제의 근원이 될 수 없습니다. –

+1

BTW, 어떻게이 컴파일 할 수 있습니다 :'("Hershy"-> Cat)'? 'Cat'은 클래스이고'Cat' 자체는 아닙니다. 난 그냥 의사 코드 같아요 - 다른 사람들이 당신이 본 적이없는 코드를 디버깅하려고 할 때 항상 혼란스럽게합니다. –

+0

아, 죄송합니다. Cat()이되어야했습니다. – noncom

답변

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

멋진 예를 들어 보았지만 그 고양이 "야옹"을 결코 잊지 마십시오 ;-) 그 중요한 비트를 잊어 버렸습니다. "Hershy를 호출하는 것"을 인쇄하는 것 외에 "야옹"도 인쇄합니다. "야옹"없이는 대답은 클로저에 불과하지 않을 수 있습니다. – virtualeyes