概括
如果我将文字表达式作为参数传递给函数,那不应该与首先评估相同的文字表达式,然后将变量绑定到从该评估返回的值,然后将变量名作为相同的参数传递到相同的功能?如果该文字表达式为函数的参数返回了错误的类型,那么跳过将值分配给一个中间变量的步骤,该变量的类型 Scala 从表达式的返回值中推断出来,不应该在之前将不兼容的类型传递给函数它引发了类型不匹配错误,应该吗?然而,这不是以下示例所显示的吗?
例子
在这里,我尝试获取类型的函数参数Array[Super]
以接受Array[Sub]
. 在 Scala repl 中声明以下内容。注意函数的单个参数的类型:
class Super
class Sub extends Super
def wantsSuperArray(a: Array[Super]) { println(a.size) }
然后构造一个实例Sub
scala> val s = new Sub
s: Sub = Sub@2c9fa2fb
创建一个Array[Sub]
:
scala> val subArray = Array(s)
subArray: Array[Sub] = Array(Sub@2c9fa2fb)
以下将表明泛型Array
在其元素类型上是不变的,并且即使 a是 a ,anArray[Sub]
也不是 a :Array[Super]
Sub
Super
scala> wantsSuperArray(subArray)
<console>:13: error: type mismatch;
found : Array[Sub]
required: Array[Super]
Note: Sub <: Super, but class Array is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: Super`. (SLS 3.2.10)
wantsSuperArray(subArray)
^
到目前为止没有任何惊喜。
令人惊讶的观察
我们刚刚看到wantsSuperArray()
不会将Array[Sub]
. 那么为什么下面不会产生与上面相同的类型不匹配错误消息呢?
scala> wantsSuperArray(Array(new Sub))
1
同样,为什么会引发这个没有错误?
scala> wantsSuperArray(Array(s))
1
考虑到编译器对这三个变体的处理与 repl 一致,即拒绝编译并为第一个提供相同的类型不匹配错误,并编译第二个和第三个。
附加细节
如果我们明确参数化Array
如下,则错误消息再次出现:
scala> wantsSuperArray(Array[Sub](new Sub))
<console>:11: error: type mismatch;
found : Array[Sub]
required: Array[Super]
Note: Sub <: Super, but class Array is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: Super`. (SLS 3.2.10)
wantsSuperArray(Array[Sub](new Sub))
^
因此,显然当不涉及中间变量时,Scala 可以看到wantsSuperArray
想要什么类型并且正在做某种转换,也许是从Array[Sub]
to转换Array[Super]
。尽管如此,这似乎是一个陷阱,因为我仍然认为是否使用中间变量的选择不应该在程序的操作中造成这样的差异,而且这种特殊情况似乎是在执行强制转换而不是引发错误程序员会期望基于泛型Array
类型参数的不变性。
问题
如果我相信在wantsSuperArray()
上面定义的调用中,传递一个文字表达式应该与传递一个变量的名称相同,该变量包含评估同一表达式所产生的值,如上所示,那么我误解了什么?
我怎样才能更好地理解我在这里观察和抱怨的内容?
我可以在 Scala 文档中的什么地方阅读我在这里观察到的现象,以便能够理解它并且再也不会对它感到惊讶?