1

在 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]”。为什么?

IDEA 抱怨参数默认值的类型问题的屏幕截图

  • IntelliJ IDEA 2016.2.4
  • Scala 插件 2016.2.1
  • 斯卡拉 2.11.7

注 1:对不起,我知道我的示例函数没有多大意义。但是,我的真实(和有用)功能过于复杂,无法在此处发布。

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

4

1 回答 1

1

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

现在来,为什么这在 REPL 中有效,我不确定为什么 REPL 接受 ifSeq[String]作为默认值,但是当我在方法主体内执行相同的操作时,我能够在 repl 中重现错误。

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

因此,当您提供默认值时,它会将 的值分配StringAny。因此编译成功。Intellij 的类型检查器基于第一个理论工作并显示错误。但奇怪的是,正如前面有人指出的那样,编译成功了。

于 2016-10-20T08:20:43.280 回答