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]”。 为什么?
- IntelliJ IDEA 2016.2.4
- Scala 插件 2016.2.1
- Scala 2.11.7
注1:抱歉,我知道我的示例函数没有多大意义。然而,我真正的(有用的)功能对于 post 这里来说是不必要的复杂。
注意 2:起初,示例中我的类型名称不是 T,而是 Any,这不是一个好主意(因为它掩盖了 scala.Any) 并造成了一些混乱。因此我解决了这个问题。
当您说 def d[Any]
时,这里的 Any
是通用占位符。它不指向 Scala 中的 class Any
。它基本上隐藏了在 scala 中全局定义的 Any
class。因此,当您将 Seq[String]
分配给 Seq[Any]
时,编译器不知道 String
和 Any
之间的任何关系。请注意,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 的类型检查器基于第一个理论工作并显示错误。但奇怪的是正如之前有人指出的那样,编译成功了。
在 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]”。 为什么?
- IntelliJ IDEA 2016.2.4
- Scala 插件 2016.2.1
- Scala 2.11.7
注1:抱歉,我知道我的示例函数没有多大意义。然而,我真正的(有用的)功能对于 post 这里来说是不必要的复杂。
注意 2:起初,示例中我的类型名称不是 T,而是 Any,这不是一个好主意(因为它掩盖了 scala.Any) 并造成了一些混乱。因此我解决了这个问题。
当您说 def d[Any]
时,这里的 Any
是通用占位符。它不指向 Scala 中的 class Any
。它基本上隐藏了在 scala 中全局定义的 Any
class。因此,当您将 Seq[String]
分配给 Seq[Any]
时,编译器不知道 String
和 Any
之间的任何关系。请注意,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 的类型检查器基于第一个理论工作并显示错误。但奇怪的是正如之前有人指出的那样,编译成功了。