Scala inheritance hierarchy diagram:
The above diagram from the book Scala for the Impatient shows that all the Java classes are subclasses of the 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.
How was that achieved without changing the Java classes? Is it something that is taken care of at the bytecode level?
Disclaimer: I'm by no way a Scala expert, but have 20 years of Java experience, including JVM.
My interpretation is that the sentence
All other classes are subclasses of the AnyRef class, which is a synonym for the Object class from the Java or .NET virtual machine.
(emphasis mine) explains it perfectly.
To the JVM, there's no AnyRef
class. The text calls AnyRef
a synonym, and the JVM doesn't have such a concept. So, probably the Scala compiler replaces occurrences of AnyRef
with java.lang.Object
. And of course, all Java classes are subclasses of java.lang.Object
, which just got a new name in the Scala compiler, thus making them all inherit from AnyRef
(a.k.a. Object
)
I bet you won't find an AnyRef.class
entry in any Scala runtime JAR library, meaning that to the JVM, a class like AnyRef
doesn't exist.
This is something that often confuses beginners. There was a very similar question on Software Engineering.SE recently. The simple answer is: MAGIC!
Yes, really.
The Scala compiler doesn't have to abide by the rules of the Scala language. In some sense, it is the rules of the Scala language! It has to implement and enforce them, but it doesn't have to follow them. And it most certainly doesn't have to follow the rules of the Java language.
So, the way it does it, is really simple: whenever some Scala program does something that depends on java.lang.String
behaving as if it was a subclass of scala.AnyRef
, it generates code that behaves as if java.lang.String
were a subclass of scala.AnyRef
.
That's it.
You could also ask how Scala makes Java primitives objects that are instances of classes which are subclasses of scala.AnyVal
. Or, you could ask how you, the programmer, can see the private implementations of two classes when you open the sourcecode of the two files in two editor windows, even though the language says that you can't see private implementations from the outside.
The reason is always the same: because you are sitting outside of the language, the language rules don't apply to you.
From the other direction, people often ask why they can subclass sealed
classes from Java or call methods declared as private[this]
. The reason is again the same: because the Java compiler doesn't have to play by Scala's rules. It doesn't even know about Scala's rules.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With