Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How was it possible to make existing Java classes subclasses of AnyRef in Scala?

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, 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.

How was that achieved without changing the Java classes? Is it something that is taken care of at the bytecode level?

like image 206
6harat Avatar asked Dec 23 '22 07:12

6harat


2 Answers

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.

like image 172
Ralf Kleberhoff Avatar answered Mar 22 '23 22:03

Ralf Kleberhoff


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.

like image 32
Jörg W Mittag Avatar answered Mar 23 '23 00:03

Jörg W Mittag