Sealed Class Basics

A Closed Family of Types

A sealed class has a fixed set of subclasses, all known at compile time (they must be in the same package and module). Unlike an enum, each subclass can carry different data and can have many instances.

Example

sealed class Shape {
    data class Circle(val radius: Double) : Shape()
    data class Rectangle(val w: Double, val h: Double) : Shape()
    data object Empty : Shape()
}

fun area(s: Shape): Double = when (s) {
    is Shape.Circle -> Math.PI * s.radius * s.radius   // smart cast: s.radius is available
    is Shape.Rectangle -> s.w * s.h
    Shape.Empty -> 0.0
}

fun main() {
    val shapes = listOf(Shape.Circle(1.0), Shape.Rectangle(2.0, 3.0), Shape.Empty)
    shapes.forEach { println("$it -> %.2f".format(area(it))) }
}

Output

Circle(radius=1.0) -> 3.14
Rectangle(w=2.0, h=3.0) -> 6.00
Empty -> 0.00

Key Facts

  • A sealed class is abstract; you cannot create it directly.
  • Subclasses can be data class, class, object / data object.
  • Its constructors are protected by default.
  • Code outside the module cannot add new subclasses.