`isInstanceOf`是如何工作的?

31
假设我们有以下内容:

假设我们有:

class B
class A extends B
trait T

那么它就保持不变:
val a: A with T = new A with T 
a.isInstanceOf[B]  // result is true !

请问,isInstanceOf 方法是否检查至少有一个类型(而非所有类型)与右侧的子类型关系匹配?

乍一看,我认为具有类型 A with T 的值不能是 B 的子类型,因为 A T 都不是 B 的子类型。但是 A 或者 TB 的子类型吗?


这是关于对象相等性的快速概述:http://joelabrahamsson.com/learning-scala-part-eight-scalas-type-hierarchy-and-object-equality/ - Jaider
2个回答

41
isInstanceOf检查继承链中是否存在相应的条目。 A with T 的链包括 ABT,因此 a.isInstanceOf[B] 必须为 true。
编辑:
实际上生成的字节码调用了 Java 的 instanceof,因此在 Java 中应该是 a instanceof B。类似 a.isInstanceOf[A with T] 的稍微复杂一点的调用应该是 (a instanceof A) && (a instanceof T)

1
谢谢您提供的背景信息,这对我很有帮助。您知道我在哪里可以找到更多关于 Scala 的 isInstanceOf 方法的背景信息吗?Scala API 对此没有提供太多信息。 - John Threepwood
没有太多可以说的,只是 instanceof - drexin

13
乍一看,我认为带有类型A和T的值不能成为B的子类型。
这里有两个误解。首先,实例的静态类型对isInstanceOf的结果没有任何影响:没有任何影响。明确一下,当执行a.isInstanceOf[B]时,aA with T类型不相关
方法isInstanceOf在JVM的字节码级别上实现。它查看每个实例携带的类信息,并检查B是否是其中一个类(实例本身及其祖先的类)或一个已实现的接口。那就是“is-a”关系:“a是B”。
从技术上讲,isInstanceOf是Java反射的一部分,在其中被称为instanceof
第二个误解是继承可以以某种方式删除父类型。这永远不会发生:继承只添加类型,从不删除它们。类型A with TABTAnyValAny。因此,即使isInstanceOf查看类型A with T,它仍将返回true。

你知道我如何在REPL中证明NullNothing是所有东西的子类型吗? "A".isInstanceOf [Null]会出错吗? Nothing也是一样吗?我猜这很有道理;即在Java中,"A" instanceof null不起作用。我只需要相信文档上的说法吗? - Toby
@Toby 在Java中不存在Nothing,因为它将类和基元视为不同的事物,而instanceof仅适用于前者。此外,在Java中也不存在Null,因为它没有“底部”的概念。 - Daniel C. Sobral

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接