2011-04-08 59 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