Sam Stites

Trait Internals

In the end, Scala needs to translate traits into classes and interfaces for the JVM to be able to handle them.

A trait with only abstract methods is converted into a Java Interface. If a trait has concrete fields, a companion class is created alongside the interface whose static fields hold the trait’s values.

trait ConsoleLogger extends Logger {
  val maxLength = 15
  def log(msg: String) { println(msg) }
}

turns into

public interface ConsoleLogger extends Logger {
  public abstract int maxLength();
  public abstract void hash_prefix$maxLength_$eq(int);
  void log(String msg);
}

// Companion Class
public class ConsoleLogger$class {
  public void $init$(ShortLogger self) {
    self.hash_prefix$maxLength_$eq(15);
  }
  public static void log(ConsoleLogger self, String msg) {
    println(msg);
  }
}

When the trait is mixed into a class, the class will get the appropriate getters and setters. The constructor of said class will also be initialized with the appropriate variables if needed. Finally, if a trait extends a superclass then the companion class will not acutually inherit the superclass. Instead, any class implementing the trait will inherit it.

Pretty cool - It’s always interesting to look under the hood, especially with what they’re doing with this language!