Both help you represent restricted class hierarchies, ensuring that all possible subclasses or implementations are known at compile time.

credits : unsplash
Introduction
- When you start exploring advanced Kotlin concepts, you’ll quickly come across the term “sealed” — both sealed classes and sealed interfaces.
- But when should you use a sealed class, and when is a sealed interface a better fit?
Let’s go through both in depth:
Sealed Class
- A sealed class in Kotlin is used to restrict inheritance to a predefined set of subclasses.
- Think of it like an enum with extra flexibility — each subclass can hold different data types or logic.
- We use an enum for simple constants, and a sealed class when your states carry contextual data or behaviour.
- Here,
UiStatecan only have these three types —Success,Error, andLoading.

- You can use it in a
whenexpression without needing anelsebranch:

- A sealed class can have a constructor and therefore can hold properties (state) that are common to all its subclasses.
- A class can only extend one other class (the sealed class). This restricts the subtypes to a single inheritance path.
All direct subclasses must be in the same file as the sealed parent (unless the parent is in the same compilation unit since Kotlin 1.9).
Sealed Interface
- A sealed interface is similar — it restricts which classes can implement it — but it provides more flexibility because classes can implement multiple interfaces.

- You can now have a class that implements multiple sealed interfaces if needed:

- A sealed interface cannot have a constructor, meaning the sealed type itself cannot hold state
- A class can implement multiple interfaces. This is the main advantage of a sealed interface, as a subtype can implement the sealed interface and also extend another class or implement other interfaces.
In simple terms, a sealed interface focuses on providing more flexibility while writing code.
When to Use Which
- Sealed Class : when the hierarchy represents different states of a single entity, and you need the base type to potentially hold common data or logic. This is common for state management (e.g., network results, UI states).Each subclass needs to hold different data.
- Sealed Interface : when the hierarchy represents a closed set of types that share common behaviour (defined in the interface’s methods) but might need to be part of other, unrelated class hierarchies. You want to define contracts or capabilities that a type can have.
Both sealed classes and sealed interfaces can now be top-level or nested.
Variance Support
- Variance Support —
outandinwith Sealed Interfaces. - One more powerful difference is that sealed interfaces support generic variance modifiers — like
out(covariance) andin(contravariance) — whereas sealed classes do not. - Let’s understand what that means with a small example:

- Here,
Response<out T>means it’s covariant — you can safely assign aResponse<String>to a variable of typeResponse<Any>.

- This is especially useful when working with generic result wrappers for APIs or repositories, as it keeps your code design both flexible and type-safe.
- If you try to do the same with a sealed class:

- This restriction exists because sealed classes are concrete class hierarchies, not type contracts. Variance only makes sense for interfaces that describe type relationships.
- Sealed classes and interfaces make your Kotlin code more type-safe and readable — especially when modeling UI states, network responses, or domain events.
- So, if you’re designing generic, type-safe result hierarchies — like
Response<T>,UiState<T>, orAction<T>— it’s often better to use a sealed interface instead of a sealed class.
Job Offers
Reference link
- https://kotlinlang.org/docs/sealed-classes.html
- So next time you design your domain or presentation layer, pause and ask “Do I want a closed set of states, or a flexible set of behaviours?”
Happy coding 💻✨ — Until then, if you learned something new today that helped you understand in detail — please drop a few claps to support my writing! 👏
Take Care 🙂
This article was previously published on proandroiddev.com



