为啥 Scala 在使用按名称参数重载的情况下的行为与使用按值参数的情况不同?
Posted
技术标签:
【中文标题】为啥 Scala 在使用按名称参数重载的情况下的行为与使用按值参数的情况不同?【英文标题】:Why is Scala's behavior in case of overloading with by-name parameters different from the case with by-value parameters?为什么 Scala 在使用按名称参数重载的情况下的行为与使用按值参数的情况不同? 【发布时间】:2011-05-18 12:39:06 【问题描述】:鉴于此 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) 编译正确,但 byname 编译失败:
ambiguous reference to overloaded definition
为什么?我希望在重载方面观察到按值和按名称参数的相同行为......如何解决?
【问题讨论】:
【参考方案1】:那是因为 JVM 不支持“按名称”参数,所以 Scala 必须以另一种方式实现它。 => X
实际上编译为 Function0[X]
,而后者会擦除为 Function0[Object]
,这使得 Scala 无法区分两种方法,它们仅在预期的别名参数类型上有所不同。
【讨论】:
谢谢丹尼尔,这解释了原因。现在如何才能解决这个问题(如果可能的话)? @JPP 这是一个以前被问过的问题。一种简单的方法是使第一个参数是强制性的,而不是可变参数的一部分。其他方法涉及隐式参数,但我不记得确切的技巧。 @JPP:在这种特殊情况下不要使用重载。 scala-programming-language.1934581.n4.nabble.com/…【参考方案2】:如果您不想使用不同的方法名称,则无需重载的可能解决方法(除了前面所说的):
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")
【讨论】:
以上是关于为啥 Scala 在使用按名称参数重载的情况下的行为与使用按值参数的情况不同?的主要内容,如果未能解决你的问题,请参考以下文章