🧷 Kotlin – Sealed Classes: Restricted Class Hierarchies for Safer Code
🧲 Introduction – Why Learn Kotlin Sealed Classes?
Sealed classes in Kotlin are used to define a restricted class hierarchy, meaning all possible subclasses are known at compile time. This makes them perfect for representing state machines, result types, error handling, or sealed hierarchies for pattern matching using when
. Sealed classes are also extremely useful in modern Android architectures like MVI and Jetpack Compose state models.
🎯 In this guide, you’ll learn:
- What sealed classes are and how they work
- How they differ from abstract and enum classes
- How to use them with
when
expressions safely - Real-world use cases and best practices
🧩 What Is a Sealed Class in Kotlin?
A sealed class restricts subclassing:
- All subclasses must be declared in the same file
- Helps the compiler know all possible types at compile time
✅ Basic Syntax:
sealed class Result
Subclasses:
class Success(val data: String) : Result()
class Error(val exception: Exception) : Result()
✔️ You must define all subclasses in the same Kotlin file.
🧪 Using Sealed Classes with when
fun handleResult(result: Result) {
when (result) {
is Success -> println("Success: ${result.data}")
is Error -> println("Error: ${result.exception.message}")
}
}
✔️ No else
branch is required—Kotlin knows all cases are covered!
🧱 Sealed Class vs Abstract Class vs Enum
Feature | sealed class | abstract class | enum class |
---|---|---|---|
Subclasses in same file | ✅ Required | ❌ No | ✅ All enum constants predefined |
Supports state & data | ✅ Yes | ✅ Yes | ✅ Yes, limited |
Exhaustive when check | ✅ Yes | ❌ No | ✅ Yes |
Useful for | State models, results, patterns | Base logic inheritance | Finite sets of constants |
🔄 Sealed Class with Data
sealed class ApiResponse {
data class Success(val result: String) : ApiResponse()
data class Failure(val code: Int, val message: String) : ApiResponse()
object Loading : ApiResponse()
}
🔹 Usage:
fun handle(response: ApiResponse) {
when (response) {
is ApiResponse.Success -> println("Got: ${response.result}")
is ApiResponse.Failure -> println("Error ${response.code}: ${response.message}")
ApiResponse.Loading -> println("Loading...")
}
}
🔐 Why Sealed Classes Are Safer
- Enforces exhaustive checks in
when
expressions - Avoids accidental omission of new states
- Encourages better modeling of finite and predictable data states
⚙️ Real-World Use Cases
Use Case | Why Sealed Class Fits |
---|---|
API Responses (Success , Error ) | One base type, multiple fixed outcomes |
UI State (Loading , Success , Error ) | Pattern-match cleanly in viewmodels |
Command handling (Command.A , Command.B ) | Each command type is well-defined |
Navigation events | Fixed navigation flows across screens |
🚫 Common Mistakes
❌ Mistake | ✅ Fix |
---|---|
Defining subclasses in other files | All subclasses must be in the same Kotlin file |
Using sealed class when enum is enough | Prefer enum for simple constant-like hierarchies |
Not using when exhaustively | Always use full when matching for clarity |
Adding logic to base sealed class | Keep sealed base class minimal—logic goes in subclasses |
✅ Best Practices for Kotlin Sealed Classes
Practice | Why It Matters |
---|---|
Use data classes for stateful subclasses | Enables immutability and destructuring |
Use object for stateless singletons | Memory efficient and expressive |
Use when without else | Forces safer handling of all subclasses |
Group subclasses inside the same file | Required for sealed class to function properly |
📌 Summary – Recap & Next Steps
Sealed classes in Kotlin allow you to model restricted, controlled hierarchies that ensure safe and exhaustive handling in when
expressions. They’re powerful tools for modern Kotlin app architecture.
🔍 Key Takeaways:
- Use
sealed
to define a limited set of subclasses in one file - Works great with
when
expressions—noelse
needed - Supports
data class
andobject
types for modeling state - Ideal for UI states, API results, and logic branching
⚙️ Practical Use:
Perfect for MVI state machines, API response modeling, UI state handling, and command processing in Kotlin applications.
❓ FAQs – Kotlin Sealed Classes
❓ What is a sealed class used for in Kotlin?
✅ A sealed class is used to represent a restricted set of types, perfect for modeling finite states or branching logic.
❓ Can sealed class subclasses be defined in other files?
✅ No. All subclasses of a sealed class must be in the same file.
❓ Can sealed class have data
subclasses?
✅ Yes. This is a common practice to store structured data per subclass.
❓ How are sealed classes different from enums?
✅ Enums are limited to predefined constants; sealed classes allow richer, stateful subclasses with different data types.
❓ Can a sealed class be abstract?
✅ Yes, and often it is—though you don’t need to mark it abstract
, because you can’t instantiate a sealed class directly.
Share Now :