views:

220

answers:

3

Why do all Scala classes inherit from ScalaObject although that trait is completely empty and has no (visible?) functionality compared to AnyRef, which does define additional methods?

Won't that slow down method calls like equals() or hashCode() because it will need to take another class into consideration (which might override the methods)?

Isn't it possible to fold AnyRef and ScalaObject into one class?

+5  A: 

ScalaObject inserts a $tag method, which, according to the comment in the library source code for 2.7, "is needed for optimizing pattern matching expressions which match on constructors of case classes." Since the name starts with $, it should of course be considered "hidden" to application programmers. In Scala 2.8, it's entirely empty, so I guess it's there for backward compatibility.

larsmans
Why isn't that $tag method inserted into AnyRef?
soc
Backward compat, I guess. (Extended my answer after downloading and reading the 2.8 source code.)
larsmans
I've grepped through the compiler code and there's some code to handle it in a special way (file `Global.scala`), but no explanation why it's there.
larsmans
Why wasn't it removed in 2.8.0 then, considering that there is no backward compatibility to 2.7?
soc
+2  A: 

It also makes a handy hook for static analyses. For instance, imagine you had a tool which could search through a code base (compiled or not), and tell you that you could improve some metric of cohesiveness/coupling/layer-balance/what-have-you by extracting a trait from these classes and create an implicit conversions for those classes. This tool would sensibly only report on traits that could profitably be extract from classes that inherit ScalaObject, while reporting profitable implicit conversions from any Java class. The same tool would report on any possible "null" returns from ScalaObject sub-classes (where Option or similar is usually a better choice), while ignoring null returns from Java classes.

Dave Griffith
+3  A: 

Method dispatching does not chain up the class inheritance structure looking for implementations. The compiler constructs a net method dispatch table for each class that reflects its net override / inherited method lineage. It's one of the virtues of statically resolving all typing.

Randall Schulz