BradCypert.com
Kotlin Sealed Classes
October 19, 2018

Kotlin Sealed Classes

Posted on October 19, 2018  (Last modified on December 27, 2022 )
3 minutes  • 634 words
This project uses these versions of languages, frameworks, and libraries.
  • kotlin kotlin : 1.2.60
This tutorial may work with newer versions and possibly older versions, but has only been tested on the versions mentioned above.

Kotlin has a concept known as sealed hierarchies (several other languages implement this feature as well). In Kotlin, we can generate a sealed hierarchy through the use of sealed classes.

What are Sealed Classes?

Sealed classes are basically an extension to an enum class. They offer similar functionality with a few key differences. Similarly:

Differences however, are the important part:

Defining Sealed Classes

In Kotlin, the sealed keyword can be used to construct a Sealed Class.

sealed class CalendarFormat

Following the idea of a type for a CalendarFormat, let’s set a few expectations:

  1. Our Calendar can be formatted in days, weeks, months, or years.
  2. We need to account for leap years where applicable.

We need to create our CalendarFormat. That’s our end goal, after all. We could start with an enum for this as well, but to determine if that permutation is a leap year, we’d need every, we’d need every permutation of that enum to also implement a method to determine if it is a leap year. That would give us something like this:

enum class CalendarFormat {
  DAY {
    override fun isLeapYear(): Boolean = false
  },
  WEEK {
    override fun isLeapYear(): Boolean = false
  },
  MONTH {
    override fun isLeapYear(): Boolean = false
  },
  YEAR {
    override fun isLeapYear(): Boolean {
      // new up a date and figure out if its a leap year
      return true
    }
  }

  abstract fun isLeapYear(): Boolean
}

Obviously, this isn’t ideal. If we add MORE enum types, we have to implement isLeapYear for all of them. Using a sealed class is a better solution here. Let’s do that instead.

sealed class CalendarFormat {
  class Days: CalendarFormat()
  class Weeks: CalendarFormat()
  class Months: CalendarFormat()
  data class Years(val isLeapYear: Boolean): CalendarFormat()
}

That’s much better! We no longer need to implement a method on each permutation of the enum simply by using a sealed class.

Using Sealed Classes with When

One of the nice features of using an enum is the compiler support for ensuring you cover all your cases with a when statement. You might be familiar with the following:

enum class Color {
  RED, BLUE, GREEN
}

fun colorStuff(color: Color): String {
  return when(color) {
    Color.RED -> "red"
    Color.BLUE -> "blue"
    Color.GREEN -> "green"
  }
}

If you don’t cover each available case in a when expression, you’ll be warned by the compiler that you’re handling all of your possible cases. Nice! However, this feature is also available with sealed classes. Going back to our previous Calendar example, we can do something like this:

sealed class CalendarFormat {
  class Days: CalendarFormat()
  class Weeks: CalendarFormat()
  class Months: CalendarFormat()
  data class Years(val isLeapYear: Boolean): CalendarFormat()
}

class Calendar {
  // this would ideally, have some calendar related logic in it
}

// exchange Calendar(...) with an actual constructor call.
fun buildCalendar(format: CalendarFormat): Calendar {
  return when (format) {
    is CalendarFormat.Days -> Calendar(...)
    is CalendarFormat.Weeks -> Calendar(...)
    is CalendarFormat.Months -> Calendar(...)
    is CalendarFormat.Years ->  Calendar(..., isLeapYear = format.isLeapYear)
  }
}

Its important to note that is CalendarFormat.Years -> will smart-cast the format to a Year. After the smart cast, we will have access to the members and functions on that Year object.

Conclusion

And that’s a quick primer on sealed classes. You can learn more at the documentation page on sealed classes . Interested in learning more about Kotlin? Check out my other Kotlin articles here !

Cartoon headshot of Brad Cypert
Follow me

Connect with me to follow along on my journey in my career, open source, and mentorship. Occasionally, I'll share good advice and content (quality not guaranteed).