Почему поведение Scala в случае перегрузки параметрами по имени отличается от случая с параметрами по значению? - PullRequest
9 голосов
/ 01 декабря 2010

Учитывая этот код Scala:

object test {

  def byval(a: Int) = println("Int")
  def byval(a: Long) = println("Long")

  def byname(a: => Int) = println("=> Int")
  def byname(a: => Long) = println("=> Long")

  def main(args: Array[String]) {
      byval(5)
      byname(5)
  }
}

, вызов byval (5) компилируется правильно, но по имени не удается скомпилировать:

ambiguous reference to overloaded definition

Почему?Я ожидал бы наблюдать такое же поведение для параметров по значению и по имени в отношении перегрузки ... Как это можно исправить?

Ответы [ 2 ]

14 голосов
/ 01 декабря 2010

Это потому, что JVM не поддерживает параметр "по имени", поэтому Scala должен реализовать его по-другому. => X фактически компилируется в Function0[X], который стирается в Function0[Object], что делает невозможным для Scala различать два метода, которые отличаются только ожидаемым типом параметра по имени.

6 голосов
/ 01 декабря 2010

Возможный обходной путь без перегрузки (в дополнение к тому, что было сказано ранее), если вы не хотите использовать разные имена методов:

def byname[A](a: => A)(implicit manifest:Manifest[A]) = 
manifest.erasure match {
   case erasure if(erasure.isAssignableFrom(classOf[Long])) => println("=> Long")
   case erasure if(erasure.isAssignableFrom(classOf[Int])) => println("=> Int")
}
...