History of the question:
Interfaces with the sealed modifier appeared in Kotlin as an evolution of the sealed class concept. Prior to Kotlin 1.5, only sealed classes allowed restricting the set of possible subclasses, which is especially important for safely working with state hierarchies (state machines, DSL, etc.). By introducing sealed interfaces, developers provided a way to similarly restrict implementations of interfaces without tying them to classes.
Problem:
A simple open interface can be implemented anywhere in the program, which may lead to uncontrolled growth in the number of implementations and complicate code maintenance. When processed through a when expression, the compiler cannot warn about unaccounted branches.
Solution:
A sealed interface restricts implementations only to those defined in the same module (or the same file if the interface is not top-level). This type of control is applied for safe enum-like structures, the ADT pattern, and state handlers. The compiler knows all implementations and helps with code analysis.
Code example:
sealed interface NetworkResult class Success(val data: String): NetworkResult class Error(val cause: Throwable): NetworkResult object Loading: NetworkResult fun handleResult(result: NetworkResult): String = when (result) { is Success -> "Success with ${result.data}" is Error -> "Error: ${result.cause.message}" Loading -> "Loading..." }
Key features:
when expressions: the compiler checks for exhaustiveness.Can a sealed interface be implemented outside the current file?
Answer: Unlike sealed classes, sealed interfaces can be implemented in other files, but only within the current module (or compilation unit if the interface is not top-level).
Can sealed interfaces have open methods with default implementations?
Yes, like regular interfaces, a sealed interface can contain default function implementations.
sealed interface Mode { fun description(): String = "Unknown mode" }
Is it possible to serialize a sealed interface using standard serializers (for example, kotlinx.serialization)?
Yes, but all implementations need to be explicitly specified. Support for sealed interfaces in kotlinx.serialization did not appear immediately; it is important to explicitly specify serializable types.
A sealed interface for all types of UI states was described in the project, but implementations began to appear in different parts of the application. Later, a new state type was added, and the handling block was forgotten to be updated, leading to the new state being ignored in the logs.
Pros:
Cons:
A sealed interface was used for all network responses. Because of this, when adding a new response type, the IDE immediately highlighted all places where the handling is switched using when. The error is corrected right away, with no unexpected gaps in the logic.
Pros:
Cons: