Scala traits implementation and interoperability. Part I: Basics

Traits in Scala are similar to interfaces, but much more powerful. They allow implementations of some of the methods, fields, stacking, etc. But have you ever wondered how are they implemented on top of JVM? How is it possible to extend multiple traits and where the implementations go to? In this article, based on my StackOverflow answer, I will give several trait examples and explain how scalac implements them, what are the drawbacks and what you get for free. Often we will look at compiled classes and decompile them to Java. It’s not essential knowledge, but I hope you’ll enjoy it. All examples are compiled against Scala 2.10.1.

Simple trait with no method implementations

The following trait:

trait Solver {
def answer(question: String): Int
}

compiles down to the most boring Java interface:

public interface Solver {
int answer(String);
}

There is really nothing special in Scala traits. That also means that if you ship Solver.class as part of your library, users can safely implement such interface from Java code. As far as java/javac is concerned, this is an ordinary Java compiled interface.

That… is… weird… Apparently we missed one new class file, Solver$class.class. Yes, the class is named Solver$class, this is valid even in Java. This is notSolver.class expression which returns Class[Solver], it’s apparently an ordinary Java class named Solver$class with a bunch of static methods. Here is how it looks like:

Do you see the trick? Scala created a helper Solver$class and methods that are implemented inside trait are actually placed in that hidden class. BTW this is not a companion object, it’s just a helper class invisible to you. But the real trick is $this parameter, invoked as Solver$class.ultimateAnswer(this). Since we are technically in another object, we must somehow get a handle of a realSolver instance. It is like OOP but done manually. So we learned that method implementations from traits are extracted to a special helper class. This class is referenced every time we call such a method. This way we don’t copy method body over and over into every single class extending given trait.

Extending multiple traits with implementations

Imagine extending multiple traits, each implementing distinct set of methods:

Traits with fields

Fields are another interesting feature of traits. This time let’s use a real-world example from Spring Data project. As you know interfaces can require certain methods to be implemented. However they can’t force you to provide certain fields (or provide fields on their own). This limitation becomes painful when working with Auditable<U, ID> interface extending Persistable<ID>. While these interfaces merely exist to make sure certain fields are present on your @Entity class, namely createdBy, createdDate, lastModifiedBy, lastModifiedDate and id, this cannot be expressed cleanly. Instead you have to implement the following methods in every single entity extending Auditable:

Moreover, every single class must of course define fields highlighted above. Doesn’t feel DRY at all. Luckily traits can help us a lot. In trait we can define what fields should be created in every class extending this trait:

There is actually much more, but you get the idea. So fields aren’t refactored into a separate class, but that was to be expected. Instead fields are copied into every single class extending this particular trait. In Java we could have used abstract base class for that, but it’s nice to reserve inheritance for real is-a relationships and do not use it for dummy field holders. In Scala trait is such a holder, grouping common fields that we can reuse across several classes.

What about Java interoperability? Well, IAmAuditable is compiled down to Java interface, thus it doesn’t have fields at all. If you implement it from Java, you gain nothing special. We covered basic use cases for traits in Scala and their implementation. In the next article we will explore how mixins and stackable modifications work.

Newsletter

Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

Email address:

Join Us

With 1,043,221 monthly unique visitors and over 500 authors we are placed among the top Java related sites around. Constantly being on the lookout for partners; we encourage you to join us. So If you have a blog with unique and interesting content then you should check out our JCG partners program. You can also be a guest writer for Java Code Geeks and hone your writing skills!

Disclaimer

All trademarks and registered trademarks appearing on Examples Java Code Geeks are the property of their respective owners. Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries. Examples Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.