Scala Sealed Hierarchies
A sealed trait is a trait with a closed set of subtypes. The compiler therefore knows every subtype when it checks a match.
A sealed match covers the rectangle
Shape has two subtypes in this program. The rectangle case gives its area.
sealed trait Shape
case class Circle(r: Double) extends Shape
case class Rect(w: Double, h: Double) extends Shape
@main def main(): Unit =
val s: Shape = Rect(2.0, 3.0)
val area = s match
case Circle(r) => 3.14 * r * r
case Rect(w, h) => w * h
println(area)The same match covers the circle
The circle case uses the same sealed match. No catch-all case is needed.
sealed trait Shape
case class Circle(r: Double) extends Shape
case class Rect(w: Double, h: Double) extends Shape
@main def main(): Unit =
val s: Shape = Circle(2.0)
val area = s match
case Circle(r) => 3.14 * r * r
case Rect(w, h) => w * h
println(area)A third subtype adds a third case
Adding Triangle adds one more subtype. The match gains one more case to stay exhaustive.
sealed trait Shape
case class Circle(r: Double) extends Shape
case class Rect(w: Double, h: Double) extends Shape
case class Triangle(b: Double, h: Double) extends Shape
@main def main(): Unit =
val s: Shape = Triangle(4.0, 5.0)
val area = s match
case Circle(r) => 3.14 * r * r
case Rect(w, h) => w * h
case Triangle(b, h) => b * h / 2
println(area)Example
sealed trait Shape
case class Circle(r: Double) extends Shape
case class Rect(w: Double, h: Double) extends Shape
def area(s: Shape): Double = s match
case Circle(r) => 3.14 * r * r
case Rect(w, h) => w * h
@main def main(): Unit =
println(area(Circle(2.0)))
println(area(Rect(2.0, 3.0)))Key points
- Sealed trait: a trait whose subtypes form a closed set that cannot grow by surprise.
- Use a sealed trait for a small set of kinds that belong together.
- Each subtype is a case class or a case object that extends the sealed trait.
- A match over a sealed trait needs a case for every subtype.
- With every case covered, no catch-all case is needed.
In this example, area matches over the sealed Shape trait. It has a case for Circle and a case for Rect, so both calls run. The two printed areas prove both cases work.
Note
a missing case throws MatchError at run time if that value arrives.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Scastie
Exercise
Shape is sealed with subtypes Circle and Rect. Which match is exhaustive with no catch-all?