Traits & Mixins
Linearization: traits are applied right to left; super refers to the next trait in the linearized order.
13.1 Traits — interfaces with implementation
trait Greeter:
def name: String // abstract
def greet(): String = s"Hello from $name" // concrete
trait Logger:
def log(msg: String): Unit = println(s"[LOG] $msg")
class Service(val name: String) extends Greeter, Logger // Scala 3 (Scala 2: with)13.2 Trait parameters (Scala 3)
trait Named(val label: String)
class Item extends Named("item")13.3 Stackable modifications & linearization
Linearization: traits are applied right to left; super refers to the next trait in the linearized order.
abstract class IntQueue:
def put(x: Int): Unit
def get(): Int
class BasicQueue extends IntQueue:
private val buf = scala.collection.mutable.ArrayBuffer.empty[Int]
def put(x: Int) = buf += x
def get() = buf.remove(0)
trait Doubling extends IntQueue:
abstract override def put(x: Int) = super.put(2 * x)
trait Incrementing extends IntQueue:
abstract override def put(x: Int) = super.put(x + 1)
val q = new BasicQueue with Incrementing with Doubling
q.put(10)
q.get() // 21 — Doubling runs first (rightmost), then Incrementing13.4 Self types
trait UserRepo:
def find(id: Int): String
trait UserService:
this: UserRepo => // requires a UserRepo to be mixed in
def describe(id: Int) = s"User: ${find(id)}"13.5 Transparent & sealed traits
sealed trait Shape // all subtypes in this file → exhaustive matching
transparent trait Kind // not inferred as a type (Scala 3)13.6 Universal traits & mixin composition patterns
The "cake pattern" (self types for DI) was popular in Scala 2; today prefer constructor injection, givens, or ZIO layers.