Kotlin — Sealed classes vs Sealed interface

Armando Picón
3 min readMar 19, 2024

--

“an army of bugdroid with shields safeguarding a castle” — image generated by Midjourney

Some developers often have difficulties choosing between these two sealed components, so I intend to provide some clarity to help them understand when they use one or the other with this short article.

Note for Spanish native speakers: Si eres hispanohablante y no tienes claro lo que es una Sealed class puedes visitar este artículo escrito en el 2020 por Facundo Rodríguez Arceri llamado “Sealed classes en Kotlin: ¿Por qué y para qué?” que sigue vigente aún y puede servirte como base para luego volver a este artículo.

Let’s begin with the basis…

Why do we create a class or an interface regularly? I think answering this question could help us find reasons to choose between both sealed components.

A class can represent states and entities, while an interface helps us declare what behaviors are supported by a class but without describing how or creating a contract.

Sealed class

For instance, think about the state of a User profile screen with some data to be displayed. We usually represent creating a class like this:

class UserProfileScreen(
val name:String,
val address:String,
val tags:List<String>
)

Even though this class can represent the state of the screen when the data is displayed to the users, we know that we’ll need at least one additional state to cover the loading state.

We could add a loading attribute to our UserProfileScreen class, which could violate the Single Responsibility principle. So here is when a Sealed class can help us.

sealed class UserProfileState
data class UserProfileScreen(
val name: String,
val address: String,
val tags: List<String>
) : UserProfileState()
data object LoadingUserProfileScreen : UserProfileState()

Now, we have a better representation of the states, which is easier to identify and understand. But what do we gain by declaring states in this way?

  • By default, every class in Kotlin is final, so you can’t create an inheritance without marking the parent class as open.
  • Make it possible to declare attributes to be shared by each subclass that extends the sealed class.

Sealed interface

One way you can take a sealed interface is to declare common classes that are not exactly to be used in the same context. This is opposite to a sealed class that defines related types for the same context.

I will take the example provided by the official documentation.

// Create a sealed interface
sealed interface Error

// Create a sealed class that implements sealed interface Error
sealed class IOError(): Error

// Define subclasses that extend sealed class 'IOError'
class FileReadError(val file: File): IOError()
class DatabaseError(val source: DataSource): IOError()

// Create a singleton object implementing the 'Error' sealed interface
object RuntimeError : Error

Even though we declare error types, we can distinguish between those errors related to I/O operations and those related to runtime errors.

Conclusion

I did not want to be exhaustive about definitions and scenarios to use sealed classes or interfaces, only to mention something that would be helpful to identify when you can use one or the other.

Sealing a class or an interface lets you safeguard the possible states of any modification outside the scope of the package where these classes were declared. It is particularly helpful when you are creating libraries.

As the documentation mentions, you can use the sealed classes and interface with when expressions; it allows the compiler to check that all possible cases are covered.

And that’s it; I hope this brief article will be useful. I’m open to receiving comments about how you use these sealed components or if you have other criteria to choose between them.

See you next time…

References & other articles

--

--

Armando Picón
Armando Picón

Written by Armando Picón

lifelong learner • 👨🏽‍💻 Android eng (ex: @uber ) • 🇵🇪 @ 🇨🇱 • @gdgopen • content creator @devpicon | @primosauda

No responses yet