2011-04-08 40 views
3
val eventListeners = new HashMap[Class[Event], ArrayBuffer[Event => Unit]] 

    def addEventListener[A <: Event](f: A => Unit)(implicit mf: ClassManifest[A]): A => Unit = { 
    eventListeners.getOrElseUpdate(mf.erasure.asInstanceOf[Class[Event]], ArrayBuffer[Event => Unit]()) += f 
    f 
    } 

拋出:這是一個類型不匹配?

error: type mismatch; 
found : (A) => Unit 
required: (this.Event) => Unit 
    eventListeners.getOrElseUpdate(mf.erasure.asInstanceOf[Class[Event]], ArrayBuffer[Event => Unit]()) += f 

爲什麼說它發現(A) => Unitf的值是一個函數(Event) => Unit。不是A只是一個類型參數,不是簽名?

調用示例: addEventListener { e:FooEvent => .... }

回答

7

Function1是它的參數禁忌變異。即,它的類型是Function1[-T, +R]

也就是說的Any => Unit一個功能是Event => Unit一個亞型,但對於AEvent一個亞型,A => UnitEvent => Unit一個_super_type。

問題,這個問題。如果將類型參數更改爲A >: Event,它應該可以工作。

4

你看好你的ArrayBuffer,你將給它可以採取任何Event並把它變成一個Unit(大概做一些沿途有趣)的功能。

但是你給它的功能只能採取A s,其中可能不包括所有Event s。這顯然不是你所承諾的,所以編譯器會抱怨。

你需要弄清楚在這種情況下應該發生什麼,並相應地編寫代碼。例如,您可以創建一個新函數g,該函數在收到Event時根本不會執行任何操作,根據您的類清單,它不是A,否則將應用f。或者你可以要求所有聽衆進行各種各樣的事件,並且自己負責丟掉他們不想要打擾的事件。


編輯:只是爲了讓事情用一個例子更清晰,

abstract class Fruit { def tasty: String } 

class Banana extends Fruit { def tasty = "Yum!" } 

abstract class SeededFruit extends Fruit { 
    def seedCount: Int 
    def tasty = "Mmm, mmm." 
} 

class Peach extends SeededFruit { def seedCount = 1 } 
class Apple extends SeededFruit { def seedCount = 5 } 

val tellAboutSeeds = (sf: SeededFruit) => println("There are "+sf.seedCount+"seeds") 

val fruitTeller = new collection.mutable.ArrayBuffer[Fruit=>Unit] 
fruitTeller += tellAboutSeeds // If this worked... 
fruitTeller(0)(new Banana)  // ...we'd be in trouble! 
+0

不是'A <:Event'使得它''A' *確實*包含所有'Event's? – ryeguy 2011-04-08 20:53:35

+0

@ryeguy'A <:Event'意味着'A'是'Event'的專業化/子類型。 – ziggystar 2011-04-08 21:33:01

+0

@ziggystar:對,如果'A'是'Event'的子類型,那麼爲什麼'A => Unit'與'Event => Unit'不一樣? – ryeguy 2011-04-08 21:35:38