3

我收到以下两种方法的双重定义错误:

def apply[T](state: T, onRender: T => Graphic,
             onMouseEvent: (MouseEvent, T) => T): GraphicPanel = 
  apply(state, onRender, onMouseEvent = Some(onMouseEvent))

def apply[T](state: T, onRender: T => Graphic,
             onKeyEvent: (KeyEvent, T) => T): GraphicPanel = 
  apply(state, onRender, onKeyEvent = Some(onKeyEvent))

它们都是apply具有签名的更通用方法的方法重载:

def apply[T](state: T, onRender: T => Graphic,
             onTickEvent: Option[T => T] = None, fps: Int = 30,
             onMouseEvent: Option[(MouseEvent, T) => T] = None,
             onMouseMotionEvent: Option[(MouseEvent, T) => T] = None,
             onMouseInputEvent: Option[(MouseEvent, T) => T] = None,
             onKeyEvent: Option[(KeyEvent, T) => T] = None)

我会假设即使这些类KeyEventMouseEvent有一个共同的超类(InputEvent),编译器应该仍然能够区分它们。但是,它抛出错误:

双重定义:方法 apply:[T](state: T, onRender: T => edu.depauw.scales.graphics.Graphic, someOnKeyEvent: (java.awt.event.KeyEvent, T) => T)edu.depauw。 scales.graphics.GraphicPanel 和方法 apply:[T](state: T, onRender: T => edu.depauw.scales.graphics.Graphic, onMouseEvent: (java.awt.event.MouseEvent, T) => T)edu第 115 行的 .depauw.scales.graphics.GraphicPanel 在擦除后具有相同的类型:(state: Object, onRender: Function1, someOnKeyEvent: Function2) edu.depauw.scales.graphics.GraphicPanel

有人知道发生了什么吗?诚然,我不知道“擦除后”这个短语是什么意思,所以也许解释一下它是如何工作的可能会有所帮助。

4

1 回答 1

8

这是一个更简单的示例,显示了相同的问题:

object Example {
  def foo[T](f: Int => T) = ???
  def foo[T](f: String => T) = ???
}

=>在对符号进行脱糖后,这等效于以下内容:

object Example {
  def foo[T](f: Function[Int, T]) = ???
  def foo[T](f: Function[String, T]) = ???
}

问题是 Java 虚拟机不知道泛型(在 Scala 或 Java 中),因此它认为这两种方法如下:

object Example {
  def foo[T](f: Function) = ???
  def foo[T](f: Function) = ???
}

这显然是一个问题。

这是避免 Scala 中方法重载的众多原因之一。如果这不是一个选项,您可以使用如下技巧:

object Example {
  implicit object `Int => T disambiguator`
  implicit object `String => T disambiguator`

  def foo[T](f: Int => T)(implicit d: `Int => T disambiguator`.type) = ???
  def foo[T](f: String => T)(implicit d: `String => T disambiguator`.type) = ???
}

这在用法上看起来相同,但显然非常可怕。

于 2013-07-24T18:51:16.773 回答