这怎么会是类型不匹配呢?

发布于 2024-10-31 09:33:31 字数 767 浏览 1 评论 0原文

  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) =>单位? f 的值是一个函数,即 (Event) =>单位A 不只是一个类型参数,而不是签名吗?

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

  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
  }

Is throwing:

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

Why is it saying that it found (A) => Unit? The value of f is a function that is (Event) => Unit. Isn't A just a type parameter, not the signature?

Example call:
addEventListener { e:FooEvent => .... }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美胚控场 2024-11-07 09:33:31

Function1 类的参数是逆变的。即,其类型为Function1[-T, +R]

这意味着 Any => 的函数UnitEvent => 的子类型Unit,但对于 AEvent 的子类型,A => UnitEvent => 的 _super_type单位

因此,问题来了。如果将类型参数更改为 A >: Event,它应该可以工作。

The class Function1 is contra-variant on its parameter. Ie, its type is Function1[-T, +R].

That means a function of Any => Unit is a subtype of Event => Unit, but for A a subtype of Event, A => Unit is a _super_type of Event => Unit.

Ergo, the problem. If you change the type parameter to A >: Event, it should work.

想挽留 2024-11-07 09:33:31

您向 ArrayBuffer 承诺,您将为它提供一个可以接受任何 Event 并将其转换为 Unit 的函数(大概是在做一些有趣的事情)道路)。

但是您给它的函数只能接受 A,它可能不包含所有 Event。这显然不是你所承诺的,所以编译器会抱怨。

您需要弄清楚在这种情况下应该发生什么,并相应地编写代码。例如,您可以创建一个新函数 g,如果它收到一个 Event(根据您的类清单)不是 A,则不执行任何操作code>,否则应用 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!

You are promising your ArrayBuffer that you will give it a function that can take any Event and turn it into a Unit (presumably doing something interesting along the way).

But you are giving it a function that can only take As, which may not encompass all Events. That is clearly not what you've promised, so the compiler complains.

You need to figure out what ought to happen in that case, and write code accordingly. For example, you could create a new function g that does nothing in case it receives an Event that, according to your class manifest, is not an A, and otherwise applies f. Or you could require all listeners to take events of all sorts, and be responsible themselves for throwing away the events that they don't want to bother with.


Edit: just to make things clearer with an example,

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!
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文