我有以下代码。
object example {
def foo(a: Any) = "Object"
def foo(a: String, args: String*) = "String"
def main() = {
println(foo("ABC")) // Should print "String"
}
}
在 Scala 2 中,这段代码工作正常。当我用一个字符串参数调用 foo
时,两个重载都是有效的,但 String
一个更具体,所以它被调用。在 Scala 3 中,这是不明确的。
-- [E051] Reference Error: overloads.scala:9:12 --------------------------------------------------------------------
9 | println(foo("ABC"))
| ^^^
| Ambiguous overload. The overloaded alternatives of method foo in object example with types
| (a: String, args: String*): String
| (a: Any): String
| both match arguments (("ABC" : String))
等效代码(两个重载,其中一个更具体并且具有 vararg 参数)也适用于 Java。 Scala 3 中到底发生了什么变化,使这个特定的调用变得模棱两可?这种行为是故意的吗?在这种情况下,我如何告诉 Scala 调用哪个重载?
就其值(value)而言,我很清楚在 Scala 中强烈反对方法重载。在我的实际代码中,我正在与一个具有重载的 .append
方法的 Java 构建器类进行交互,因此我无法控制函数签名。
最佳答案
this PR 中提到了此行为, 特别是在 this comment .我不知道这是否会“修复”或者是否完全符合预期。
请注意以下内容不是有歧义的:
def foo(s: String)
def foo(a: String, other: String*)
foo("fine!")
使用 def foo(s: Any)
,您可以像这样显式地选择一个重载或另一个重载:
foo("fine": Any) // calls foo(Any)
foo("fine", Nil: _*) // calls foo(String, String*) with an empty vararg
PS:我不会说重载是“强烈反对”的,但我们必须小心并承认某些情况对于编译器和人类来说是模棱两可的。 foo("")
应该引用哪个定义对我来说并不明显,所以在这种情况下更明确一点也不是完全疯狂。
关于scala - Scala 3 中使用 Varargs 的模糊重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72469040/