Scala在Java的类型系统上叠加了一个非常优雅的类层次结构,从顶部的Any,到AnyRef和AnyVal分别覆盖Java的对象和基元,然后最终收敛,将引用类型折叠到Null,将所有类型折叠到Nothing上.据我所知,没有什么是一切的子类型; Null AnyRef/java.lang.Object的所有子类型的子类型.[见http://www.scala-lang.org/node/128 ]
但是,似乎存在一些不规则性,一些地方不能简单地将所有Scala类型视为无缝类型层次结构的元素.我觉得这很令人厌烦,想要了解我可能感到惊讶的地方.
到目前为止,我知道一些违规行为:
1)虽然Null是AnyRef的子类型,但调用null.isInstanceOf [AnyRef](或AnyRef的其他子类型)会返回false.我怀疑这被选择与Java的instanceof运算符的行为一致.
2)无论方差注释如何,一切都与Nothing协变.如果我有一个方法返回一个没有标记协变的类型T,我可以覆盖该方法返回类型Nothing.[注意:这个说法有误,请参阅下面的答案和评论!]
3)我不能将isInstanceOf应用于AnyVal类型[请参阅为什么AnyVal不能用于isInstanceOf检查?以及如何测试AnyVal的值?]
4)是违法的问是否东西isInstanceOf [空],这是要求完全一致的东西(虽然不是特别必要的,因为"myVar的== NULL"将给出相同的答案)
在Scala的类型层次结构中是否存在其他不规则或特殊情况的示例?我觉得这些值得学习和理解,以避免不受欢迎的惊喜.
1)"A string is a subtype of AnyRef".isInstanceOf[AnyRef]退货true.对于其他亚型也是如此AnyRef,除了Null.正如你所说,唯一不正常的做法是与Java保持一致.
2)如果B是的子类型A,那就是B <: A,你总是可以覆盖一个方法:
def foo: A = ...
Run Code Online (Sandbox Code Playgroud)
至:
override def foo: B = ...
Run Code Online (Sandbox Code Playgroud)
这称为精炼返回类型,并且始终允许.由于Nothing是所有其他类型的子类型(Nothing <: A对于所有A),您始终可以将返回类型细化为Nothing(例如,通过在方法体中抛出异常).这是一个非常规则的财产.返回类型协方差与类型参数的方差注释没有直接关系.
3)其他问题很好地涵盖了这一点.
4)这是因为NullJava运行时中不存在该类型.我想如果你想模仿这个,你可以创建自己的instanceOf方法 - 你首先要检查参数是否null,否则,进行正常isInstanceOf检查.
还有其他违规行为,是的.参见例如:如果Int不能为null,则null.asInstanceOf [Int]是什么意思?
数组是另一个例子,你可以instanceof在运行时通过装箱/拆箱或检查来支付通用数组的一致性.将new Array[Any]其转换为对象数组 - 将整数存储到数组中将导致对其进行装箱.无论何时使用a Array[T],其中T没有上限,每次索引元素时,数组都将与正确的运行时数组类型进行模式匹配.
为了更好地了解您如何可能会惊讶地认为这些结构是如何转换为JVM那里是原始和引用类型,装箱/拆箱和不同的数组类的概念方面,它是非常有用的.
| 归档时间: |
|
| 查看次数: |
407 次 |
| 最近记录: |