加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

方法参数类型忽略Scala不变泛型类型参数,具体取决于参数是文字表

发布时间:2020-12-16 18:04:12 所属栏目:安全 来源:网络整理
导读:摘要 如果我将一个文字表达式作为参数传递给函数,那么它不应该与首先计算相同的文字表达式相同,然后将变量绑定到从该评估返回的值,然后将变量名称作为相同的参数传递同样的功能?如果该文字表达式返回函数参数的错误类型,则跳过将值赋值给中间变量的步骤,该
摘要

如果我将一个文字表达式作为参数传递给函数,那么它不应该与首先计算相同的文字表达式相同,然后将变量绑定到从该评估返回的值,然后将变量名称作为相同的参数传递同样的功能?如果该文字表达式返回函数参数的错误类型,则跳过将值赋值给中间变量的步骤,该中间变量的类型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

创建一个数组[Sub]:

scala> val subArray = Array(s)
subArray: Array[Sub] = Array(Sub@2c9fa2fb)

以下表示通用Array is invariant in its element type,并且Array [Sub]不是数组[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可以看到wantSuperArray想要什么类型并且正在进行某种转换,可能是从Array [Sub]转换为Array [Super].不过,这似乎是一个陷阱,因为我仍然认为选择是否使用中间变量不应该导致程序操作中的这种差异,并且这种特殊情况似乎是执行转换而不是引发错误程序员期望基于通用Array类型参数的不变性.

问题

如果我相信在调用上面定义的wantsSuperArray()时,传递一个文字表达式应该与传递一个变量的名称相同,该变量包含评估相同表达式所产生的值,如上所示,那么我有什么误解?

>我如何才能提高对我观察和抱怨的理解?
>在Scala文档中我可以阅读我在这里观察到的现象,以便能够理解它并且再也不会对它感到惊讶吗?

解决方法

这是因为scala基于期望的wantsSuperArray参数类型执行类型推断.
因此,即使单独使用Array(new Sub)作为Array [Sub]类型的表达式,编译器也会看到您处于期望类型为Array [Super]的值的上下文中,因此调用Array时. apply(通用)它试图使用Super作为类型参数(而不是Sub),它正确地键入(Array.apply采用类型为T的参数的vararg列表,这里T = Super,你传递一个Sub实例,这是超级的子类型,这是声音).

以下是scala规范的相关摘录,第6.1章:表达式类型,第6.6章:函数应用程序和第6.26.4章:局部类型推断(强调我的):

The typing of expressions is often relative to some expected type (1) (which might be
undefined). When we write “expression e is expected to conform to type T ”,we
mean: the expected type of e is T,and the type of expression e must conform
to T .

An application f (e1,…,em) applies the function f to the argument expressions
e1,em. If f has a method type (p1:T1,pn:Tn)U,the type of each argument
expression ei is typed with the corresponding parameter type Ti as expected type (2)
.
Let Si be type type of argument ei (i in 1,m). If f is a polymorphic method,local
type inference is used to determine type arguments for f (3)
.

If f is a polymorphic method it is applicable if local type inference can
determine type arguments so that the instantiated method is applicable (4)*
.

Local type inference infers type arguments to be passed to expressions of polymorphic type. Say e is of type [a1 >: L1 <: U1,an >: Ln <: Un]T and no explicit type
parameters are given … If the expression e appears as a value without being applied to
value arguments,the type arguments are inferred by solving a constraint system
which relates the expression’s type T with the expected type pt (5)

点(3)和(4)解释了如何在表达式Array(new Sub)中,类型推断从new Sub流向Array.apply以产生类型Array [Sub].这是一个“简单”的案例,你显然没有问题.如果您只是采用此规则,则应将Array(new Sub)键入为Array [Sub].实际上,它是在隔离键入时发生的事情(例如在val subArray = Array(new Sub)中,subArray确实具有Array [Sub]类型).

但是第(1),(2)和(5)点一起也表示在wantsSuperArray(Array(new Sub))中,wantSuperArray(它是Array [Super])的参数的预期类型被传递给表达式Array( new Sub)(因为它是多态类型的表达式,其中未明确给出类型参数).因此,表达式Array(new Sub)被评估为表达式Array [Super](new Sub).换句话说,它被键入为Array [Super].

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读