如何在 Scala 中创建 AnyRef 的现有 Java 类 sub类?
How was it possible to make existing Java classes subclasses of AnyRef in Scala?
Scala继承层次图:
上图来自 Scala for the Impatient 一书显示所有 Java classes 都是 classes 的子classes AnyRef
class。
Figure 8–1 shows the inheritance hierarchy of Scala classes. The classes that correspond to the primitive types in Java, as well as the type Unit
, extend AnyVal
. All other classes are subclasses of the AnyRef
class, which is a synonym for the Object
class from the Java or .NET virtual machine.
Both AnyVal
and AnyRef
extend the Any
class, the root of the hierarchy.
如何在不更改 Java classes 的情况下实现这一目标?它是在字节码级别处理的吗?
免责声明:我绝不是 Scala 专家,但有 20 年的 Java 经验,包括 JVM。
我的解释是这句话
All other classes are subclasses of the AnyRef class, which is a
synonym for the Object class from the Java or .NET virtual machine.
(强调我的) 完美解释。
对于 JVM,没有 AnyRef
class。文中称AnyRef
为同义词,JVM没有这个概念。因此,Scala 编译器可能会将出现的 AnyRef
替换为 java.lang.Object
。当然,所有 Java class 都是 java.lang.Object
的子 class,它在 Scala 编译器中得到了一个新名称,因此它们都继承自 AnyRef
(a.k.a.Object
)
我敢打赌,您不会在任何 Scala 运行时 JAR 库中找到 AnyRef.class
条目,这意味着对于 JVM,class 不存在 AnyRef
。
这是经常让初学者感到困惑的事情。最近有个very similar question on Software Engineering.SE。简单的答案是:神奇!
是的,真的。
Scala 编译器不必遵守 Scala 语言的规则。从某种意义上说,它是Scala语言的规则!它必须实施和执行它们,但不必遵循它们。而且它肯定不必遵循 Java 语言的规则。
因此,它的实现方式非常简单:每当某些 Scala 程序执行某些依赖于 java.lang.String
的操作时,它的行为就好像它是 scala.AnyRef
的子类一样,它会生成具有以下行为的代码好像 java.lang.String
是 scala.AnyRef
.
的子类
就是这样。
您还可以询问 Scala 如何生成 Java 原语对象,这些对象是 类 的实例,是 scala.AnyVal
的子类。或者,你可能会问,作为程序员,当你在两个编辑器 windows 中打开两个文件的源代码时,你如何看到两个 类 的私有实现,即使语言说你不能'从外部看不到私有实现。
原因总是一样的:因为你坐在语言之外,所以语言规则对你不适用。
从另一个方向来看,人们经常问为什么他们可以从 Java 继承 sealed
类 或调用声明为 private[this]
的方法。原因还是一样的:因为 Java 编译器不必按照 Scala 的规则进行操作。它甚至不知道 Scala 的规则。
Scala继承层次图:
上图来自 Scala for the Impatient 一书显示所有 Java classes 都是 classes 的子classes AnyRef
class。
Figure 8–1 shows the inheritance hierarchy of Scala classes. The classes that correspond to the primitive types in Java, as well as the type
Unit
, extendAnyVal
. All other classes are subclasses of theAnyRef
class, which is a synonym for theObject
class from the Java or .NET virtual machine. BothAnyVal
andAnyRef
extend theAny
class, the root of the hierarchy.
如何在不更改 Java classes 的情况下实现这一目标?它是在字节码级别处理的吗?
免责声明:我绝不是 Scala 专家,但有 20 年的 Java 经验,包括 JVM。
我的解释是这句话
All other classes are subclasses of the AnyRef class, which is a synonym for the Object class from the Java or .NET virtual machine.
(强调我的) 完美解释。
对于 JVM,没有 AnyRef
class。文中称AnyRef
为同义词,JVM没有这个概念。因此,Scala 编译器可能会将出现的 AnyRef
替换为 java.lang.Object
。当然,所有 Java class 都是 java.lang.Object
的子 class,它在 Scala 编译器中得到了一个新名称,因此它们都继承自 AnyRef
(a.k.a.Object
)
我敢打赌,您不会在任何 Scala 运行时 JAR 库中找到 AnyRef.class
条目,这意味着对于 JVM,class 不存在 AnyRef
。
这是经常让初学者感到困惑的事情。最近有个very similar question on Software Engineering.SE。简单的答案是:神奇!
是的,真的。
Scala 编译器不必遵守 Scala 语言的规则。从某种意义上说,它是Scala语言的规则!它必须实施和执行它们,但不必遵循它们。而且它肯定不必遵循 Java 语言的规则。
因此,它的实现方式非常简单:每当某些 Scala 程序执行某些依赖于 java.lang.String
的操作时,它的行为就好像它是 scala.AnyRef
的子类一样,它会生成具有以下行为的代码好像 java.lang.String
是 scala.AnyRef
.
就是这样。
您还可以询问 Scala 如何生成 Java 原语对象,这些对象是 类 的实例,是 scala.AnyVal
的子类。或者,你可能会问,作为程序员,当你在两个编辑器 windows 中打开两个文件的源代码时,你如何看到两个 类 的私有实现,即使语言说你不能'从外部看不到私有实现。
原因总是一样的:因为你坐在语言之外,所以语言规则对你不适用。
从另一个方向来看,人们经常问为什么他们可以从 Java 继承 sealed
类 或调用声明为 private[this]
的方法。原因还是一样的:因为 Java 编译器不必按照 Scala 的规则进行操作。它甚至不知道 Scala 的规则。