方法参数类型忽略Scala不变泛型类型参数,具体取决于参数是文字表
摘要
如果我将一个文字表达式作为参数传递给函数,那么它不应该与首先计算相同的文字表达式相同,然后将变量绑定到从该评估返回的值,然后将变量名称作为相同的参数传递同样的功能?如果该文字表达式返回函数参数的错误类型,则跳过将值赋值给中间变量的步骤,该中间变量的类型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) 以下表示通用 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基于期望的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章:局部类型推断(强调我的):
点(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]. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- 唯品会海量实时OLAP分析技术升级之路
- 如何验证scala中的数字字符?
- angular – 如何在锚点上有条件地使用[href]或[routerLink]
- bash – 查找并替换文件中的单词
- 通过zeppelin从docker-hadoop-spark – workbench访问hdf
- angularjs – $parser.unshift ??这是如何工作的?
- 如何测试Akka演员是在Scala创建的
- angularjs – Angular.Copy返回RangeError:超出最大调用堆
- angularjs – 我如何动画排序列表与orderBy使用ng-repeat与
- 5天学会jaxws-webservice编程第四天