简体   繁体   English

Scala类层次结构中的不规则性

[英]Irregularities in the Scala class hierarchy

Scala superimposes a very elegant class hierarchy over Java's type system, balooning out from Any at the top, into AnyRef and AnyVal to cover Java's Objects and primitives respectively, then finally converging, collapsing the reference types onto Null and all types onto Nothing. Scala在Java的类型系统上叠加了一个非常优雅的类层次结构,从顶部的Any,到AnyRef和AnyVal,分别覆盖Java的对象和基元,然后最终收敛,将引用类型折叠到Null,将所有类型折叠到Nothing上。 As I understand it, Nothing is a subtype of everything; 据我所知,没有什么是一切的子类型; Null a subtype of all subtypes of AnyRef/java.lang.Object. Null AnyRef / java.lang.Object的所有子类型的子类型。 [ see http://www.scala-lang.org/node/128 ] [见http://www.scala-lang.org/node/128 ]

However, there seem to be a few irregularities, a few places where it does not work to simply think of all Scala types as elements of a seamless type hierarchy. 但是,似乎存在一些不规则性,一些地方不能简单地将所有Scala类型视为无缝类型层次结构的元素。 I find this irksome, and want to understand the places where I might be surprised. 我觉得这很令人厌烦,想要了解我可能感到惊讶的地方。

So far, I know of a few irregularities: 到目前为止,我知道一些违规行为:

1) Although Null is a subtype of AnyRef, calling null.isInstanceOf[AnyRef] (or other subtypes of AnyRef) returns false. 1)虽然Null是AnyRef的子类型,但调用null.isInstanceOf [AnyRef](或AnyRef的其他子类型)会返回false。 I suspect this was chosen to be consistent with the behavior of Java's instanceof operator. 我怀疑这被选择与Java的instanceof运算符的行为一致。

2) Everything is covariant to Nothing, regardless of variance annotations. 2)无论方差注释如何,一切都与Nothing协变。 If I have a method that returns a type T that is not marked covariant, I can override that method to return type Nothing. 如果我有一个方法返回一个没有标记协变的类型T,我可以覆盖该方法返回类型Nothing。 [NOTE: this claim is mistaken, see answers and comments below!] [注意:这个说法有误,请参阅下面的答案和评论!]

3) I can't apply isInstanceOf to the type AnyVal [ See Why can AnyVal not be used in an isInstanceOf check? 3)我不能将isInstanceOf应用于AnyVal类型[请参阅为什么AnyVal不能用于isInstanceOf检查? and How to test a value on being AnyVal? 以及如何测试AnyVal的值? ] ]

4) It is illegal to ask whether something isInstanceOf[Null], which is a perfectly coherent thing to ask (although not particularly necessary, since "myVar == null" would give the same answer) 4)询问是否有一个isInstanceOf [Null]是非法的,这是一个完全连贯的问题(尽管不是特别必要,因为“myVar == null”会给出相同的答案)

Are there other examples of irregularities or special cases in Scala's type hierarchy? 在Scala的类型层次结构中是否存在其他不规则或特殊情况的示例? I feel like these are worth learning and understanding to avoid unwelcome surprises. 我觉得这些值得学习和理解,以避免不受欢迎的惊喜。

1) "A string is a subtype of AnyRef".isInstanceOf[AnyRef] returns true . 1) "A string is a subtype of AnyRef".isInstanceOf[AnyRef]返回true This is true for other subtypes of AnyRef as well, except for Null . 对于AnyRef其他子类型也是如此,除了Null The only irregularity there is done to be consistent with Java, as you said. 正如你所说,唯一不正常的做法是与Java保持一致。

2) If B is a subtype of A , that is B <: A , then you can always override a method: 2)如果BA的子类型,即B <: A ,则可以始终覆盖方法:

def foo: A = ...

to: 至:

override def foo: B = ...

This is called refining the return type, and is always allowed. 这称为精炼返回类型,并且始终允许。 Since Nothing is a subtype of every other type ( Nothing <: A for all A ), you can always refine your return type to Nothing (eg by throwing an exception in the body of the method). 由于Nothing是所有其他类型的子类型( Nothing <: A for A ),因此您始终可以将返回类型细化为Nothing (例如,通过在方法体中抛出异常)。 This is a pretty regular property. 这是一个非常规则的财产。 The return type covariance is not directly related to variance annotations on type parameters . 返回类型协方差与类型参数的方差注释没有直接关系。

3) The other questions cover this nicely. 3)其他问题很好地涵盖了这一点。

4) This is because the Null type does not exist in the Java runtime. 4)这是因为Java运行时中不存在Null类型。 I guess if you wanted to emulate this, you could create your own instanceOf method - you would first have to check if the argument is null , otherwise, do the normal isInstanceOf check. 我想如果你想模仿这个,你可以创建自己的instanceOf方法 - 你首先要检查参数是否为null ,否则,执行正常的isInstanceOf检查。

There are other irregularities, yes. 还有其他违规行为,是的。 See for example: If an Int can't be null, what does null.asInstanceOf[Int] mean? 参见例如: 如果Int不能为null,则null.asInstanceOf [Int]是什么意思?

Arrays are another example, where you may pay the uniformity of generic arrays with boxing/unboxing or instanceof checks at runtime. 数组是另一个例子,你可以在运行时使用装箱/拆箱或instanceof检查来支付通用数组的一致性。 The new Array[Any] is translated into an object array - storing an integer into the array will result in boxing it. new Array[Any]被翻译成一个对象数组 - 将一个整数存储到数组中将导致装箱。 Whenever you use an Array[T] , where T has no upper bound, the array will be patterned matched against the correct runtime array type every time you index an element. 无论何时使用Array[T] ,其中T没有上限,每次索引元素时,数组都将与正确的运行时数组类型进行图案匹配。

To better understand how you might be surprised it's useful to think in terms of how these constructs are translated to the JVM where there is a notion of primitive and reference types, boxing/unboxing and different array classes. 为了更好地理解你可能会感到惊讶,考虑如何将这些结构转换为JVM,其中有原始和引用类型的概念,装箱/拆箱和不同的数组类是有用的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM