mixin

What def, val, and var fields in Scala traits look like after they’re compiled (including the classes that extend them)

Table of Contents1 - def field in trait2 - val field in trait (abstract)3 - val field in trait (concrete)4 - var field in trait (abstract)5 - var field in trait (concrete)6 - An abstract class in the middle7 - A trait in the middle8 - Summary

I generally have a pretty good feel for how Scala traits work, and how they can be used for different needs. As one example, a few years ago I learned that it’s best to define abstract fields in traits using def. But there are still a few things I wonder about.

Today I had a few free moments and I decided to look at what happens under the covers when you use def, val, and var fields in traits, and then mix-in or extend those traits with classes. So I created some examples, compiled them with scalac -Xprint:all, and then decompiled them with JAD to see what everything looks like under the covers.

I was initially going to write a summary here, but if you want to know how things work under the hood, I think it helps to work through the examples, so for today I’ll leave that as an exercise for the reader.

An example of stackable modifications in Scala

As a brief note today, here’s an example of stackable modifications in Scala.

Lately I was curious about what super means when you mix Scala traits into a class or object. A simplified answer is that super refers to the last trait that’s mixed in, though I should be careful and note that this is an oversimplification.

This can be demonstrated in an example that uses both inheritance and mixins with traits. Given this combination of traits and classes:

How to declare that a Scala trait can only be mixed into a type that has a specific method

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 8.7, “How to declare that a Scala trait can only be mixed into a type that has a specific method.”

Problem

You only want to allow a trait to be mixed into a type (class, abstract class, or trait) that has a method with a given signature.

Solution

Use a variation of the self-type syntax that lets you declare that any class that attempts to mix in the trait must implement the method you specify.

How to define a Scala trait so it can only be subclassed by a certain type

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 8.6, “How to mark a Scala trait so it can only be subclassed by a certain type.”

Problem

You want to mark your trait so it can only be used by types that extend a given base type.

Solution

To make sure a trait named MyTrait can only be mixed into a class that is a subclass of a type named BaseType, begin your trait with a this: BaseType => declaration, as shown here:

Scala: How to limit which classes can use a trait by inheritance

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 8.5, “How to limit which classes can use a trait by inheritance.”

Problem

You want to limit a trait so it can only be added to classes that extend a superclass or another trait.

How to use Scala traits as simple mixins

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 8.4, “How to use Scala traits as simple mixins (or, How to mix in Scala traits).”

Problem

You want to design a solution where multiple traits can be mixed into a class to provide a robust design.

Solution

To implement a simple mixin, define the methods you want in your trait, then add the trait to your class using extends or with. For instance, the following code defines a Tail trait: