About
:octocat: GitHub: All of the example code: repo (link)
:page_facing_up: blog link: https://purrgramming.life/cs/programming/fp/ :star:
Motivation
In Java, as well as in Scala, a class can only have one superclass.
But what if a class has several natural supertypes to which it conforms or from which it wants to inherit code? Here, you could use traits.
Classes, objects and traits can inherit from at most one class but many arbitrary traits.
Scala Trait vs Java Interface
Traits define reusable interfaces and behavior, including abstract/concrete members and state. Java interfaces also support default methods; the distinction is not simply whether methods can have implementations. Scala 2 traits have no constructor parameter lists; Scala 3 adds trait parameters.
Similarly to Java, in Scala, it is possible to
- have only one superclass
- can extend multiple traits (interfaces in Java)
Usage
Traits are similar to interfaces in Java and are created using trait keywords.
But what if a class has several natural supertypes to which it conforms or
from which it wants to inherit code?
Here, you could use traits.
A trait is declared like an abstract class, just with a trait instead of
abstract class
// Creating a super class
abstract class Shapes {
def draw() = println("Draw the shape")
// Overload
def draw(id: Int) = println(s"Draw the shape (Id: $id)")
}
trait MathShape {
def size: Unit
}
// Creating a subclass
class Rectangle extends Shapes with MathShape {
def size = println("length (L) * width (W) ")
}
// Creating a subclass
class Circle extends Shapes with MathShape {
// Overriding
override def draw() = println("Draw the Circle")
// Override, Overload
override def draw(id: Int) = println(s"Draw the Circle (Id: $id)")
def size = println("pi * radius^2 ")
}
val rectangle = new Rectangle
rectangle.draw()
rectangle.draw(0)
rectangle.size
val circle = new Circle
circle.draw()
circle.draw(1)
circle.size
Abstract Class vs Trait
Background reference: https://drek4537l1klr.cloudfront.net/sfregola/v-2/Figures/11_02.png

| Question | Trait | Abstract class |
|---|---|---|
| Composition | A class can mix in multiple traits, subject to compatible members. | A class can extend only one class. |
| When composed | At class definition or object construction; not retrofitted onto an already-created instance. | Chosen through class inheritance, also not retrofitted. |
| Constructor parameters | Supported in Scala 3; not in Scala 2. | Supported in both Scala 2 and 3. |
| Dispatch | Overridable instance methods use dynamic dispatch; linearization determines mixin order and super resolution. |
Overridable instance methods also use dynamic dispatch. |
| Java interop | Depends on Scala version and generated API; check how Java callers construct/implement it. | Often straightforward for shared constructor-based APIs, but still subject to types, visibility and compiler-generated details. |
Takeaway
Use traits to compose capabilities and an abstract class when a shared base class and constructor are appropriate. Neither choice makes ordinary overridden methods statically bound.
References: Scala traits; Scala 3 trait parameters.