scala - Scala 3 中使用 Varargs 的模糊重载

标签 scala overloading variadic-functions scala-3

我有以下代码。

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/

相关文章:

c++组合来自两个(或更多)参数包的值

go - 从 Go 中的可变参数创建带有可选字段的类型

scala - Scala 中的 mutable.HashTable 类

java - 被赋予子类对象值的父类(super class)对象如何执行子类的重载方法?

c++ - 重载基类函数是不好的做法吗?

C++11:通用执行器

C++ - 多态性 : initialization of a container class with derived classes

scala - 有条件地构建避免突变的列表

scala - Scala 中复制对象的简洁方法

允许对成员进行数字操作的 scala 类型签名