IntelliJ IDEA:Scala 中的默认参数值

IntelliJ IDEA: default parameter values in Scala

在 Scala REPL 中,我可以使用 Seq[String]() 作为 Seq[T] 类型参数的默认值。

Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def d[T](foo: Seq[T] = Seq[String]()) = 12
d: [T](foo: Seq[T])Int

scala> d()
res0: Int = 12

在 IDEA 中尝试相同,它抱怨“Seq[String] 不符合预期类型 Seq[T]”。 为什么?

注1:抱歉,我知道我的示例函数没有多大意义。然而,我真正的(有用的)功能对于 post 这里来说是不必要的复杂。

注意 2:起初,示例中我的类型名称不是 T,而是 Any,这不是一个好主意(因为它掩盖了 scala.Any) 并造成了一些混乱。因此我解决了这个问题。

当您说 def d[Any] 时,这里的 Any 是通用占位符。它不指向 Scala 中的 class Any。它基本上隐藏了在 scala 中全局定义的 Any class。因此,当您将 Seq[String] 分配给 Seq[Any] 时,编译器不知道 StringAny 之间的任何关系。请注意,Any 可以替换为任何字符/单词作为通用占位符。结果是一样的。

现在,为什么这在 REPL 中有效,我不确定为什么 REPL 接受 if Seq[String] 作为默认值,但是当我执行方法体内的相同操作。

REPL 中的以下代码抛出错误:

def d[Any](foo: Seq[Any]) = {
  val a: Seq[Any] = Seq[String]()
}
<console>:12: error: type mismatch;
found   : Seq[String]
required: Seq[Any]
       val a: Seq[Any] = Seq[String]()
                                    ^

我不确定为什么 REPL 在作为默认参数给出时无法捕获错误。

另一种理论是,通常当您使用泛型时,类型的值将根据调用者来确定。例如,

def d[A](a:A) = {}
d(1) // Type of A is Int
d("a") // Type of A is String

所以,当你给默认值时,它将String的值分配给Any。因此编译 success.Intellij 的类型检查器基于第一个理论工作并显示错误。但奇怪的是正如之前有人指出的那样,编译成功了。