Mastering Sealed Classes in Kotlin: Design Patterns and Better Code Organization

Hari Moradiya
3 min readJun 3, 2024

--

Introduction to Sealed Classes in Kotlin

Kotlin, a modern programming language, introduces several powerful features that enhance code readability, safety, and maintainability. One such feature is the sealed class, which offers a robust way to represent restricted class hierarchies and helps in writing cleaner, more maintainable code.

What are Sealed Classes?

Sealed classes in Kotlin are a special kind of class that allow a restricted hierarchy. Unlike regular classes, sealed classes can have a limited number of subclasses, all of which must be declared within the same file. This restriction provides a number of benefits, including exhaustive when statements and better control over the class hierarchy.

How to Use Sealed Classes?

To declare a sealed class, you use the sealed keyword before the class definition. Here's the basic syntax:

sealed class Result {
data class Success(val data: String) : Result()
data class Error(val exception: Throwable) : Result()
object Loading : Result()
}

In this example, Result is a sealed class with three subclasses: Success, Error, and Loading. Each subclass represents a different state or result.

Why We Need to Use Sealed Classes?

Sealed classes provide several advantages:

  • Exhaustive when Statements: When using a sealed class in a when statement, Kotlin ensures that all possible subclasses are covered, either explicitly or through an else clause. This helps catch potential errors at compile time.
  • Type Safety: Since all subclasses of a sealed class are known at compile time, it ensures type safety and reduces the chances of runtime errors.
  • Better Code Organization: Sealed classes help group related classes together, making the code more organized and easier to understand.
  • Enhanced Readability: By clearly defining the possible states or results, sealed classes enhance the readability and maintainability of the code.

When to use sealed classes?

Sealed classes are particularly useful in scenarios where you need to represent a fixed set of related types. Some common use cases include:

  • Representing the state in a state machine.
  • Modeling the result of a network request (success, error, loading).
  • Defining different events in an event-driven system.
  • Representing a tree or graph structure where the types of nodes are known.

Example of sealed classes

Let’s consider a simple example of a network request result to illustrate how sealed classes can be used effectively:

sealed class NetworkResult {
data class Success(val data: String) : NetworkResult()
data class Failure(val error: Throwable) : NetworkResult()
object Loading : NetworkResult()
}

fun handleResult(result: NetworkResult) {
when (result) {
is NetworkResult.Success -> {
println("Data received: ${result.data}")
}
is NetworkResult.Failure -> {
println("Error occurred: ${result.error.message}")
}
NetworkResult.Loading -> {
println("Loading...")
}
}
}

In this example:

  • The NetworkResult sealed class represents the possible outcomes of a network request: Success, Failure, and Loading.
  • The handleResult function processes the NetworkResult using a when statement. Since all possible subclasses of NetworkResult are handled, there's no need for an else clause.
That’s it

Conclusion

Sealed classes are a powerful feature in Kotlin that can help improve your code organization and design patterns. By leveraging sealed classes, you can create more robust, readable, and maintainable code. They are particularly useful for representing a restricted set of types and can be a valuable tool in your Kotlin programming toolkit.

Start incorporating sealed classes into your Kotlin projects today and experience the benefits of a more structured and error-resistant codebase!

--

--

Hari Moradiya

Android Engineer | Talk about app and SDK architecture