尽管参数类型不同,但双重定义误差

时间:2013-07-24 18:26:35

标签: scala types compiler-errors overloading

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

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),编译器仍应能够区分它们。但是,它正在抛出错误:

  

双重定义:方法适用:[T](状态:T,onRender:T =>   edu.depauw.scales.graphics.Graphic,someOnKeyEvent:   (java.awt.event.KeyEvent,T)=>   T)edu.depauw.scales.graphics.GraphicPanel和方法适用:[T](状态:   T,onRender:T => edu.depauw.scales.graphics.Graphic,onMouseEvent:   (java.awt.event.MouseEvent,T)=>   T)第115行的edu.depauw.scales.graphics.GraphicPanel具有相同的类型   擦除后:(状态:对象,onRender:Function1,someOnKeyEvent:   功能2)edu.depauw.scales.graphics.GraphicPanel

任何人都知道发生了什么事?不可否认,我不知道删除后的短语“是什么意思,所以也许对其工作方式的解释可能会有所帮助。

1 个答案:

答案 0 :(得分: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虚拟机doesn't know about generics(在Scala或Java中),因此它将以下两种方法视为:

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

这显然是一个问题。

这是避免Scala中方法重载的many reasons之一。如果这不是一个选项,你可以使用如下的技巧:

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) = ???
}

看起来用法相同,但显然很可怕。