Sealed Classes and Interfaces
Sealed classes and interfaces provide controlled inheritance of your class hierarchies.
All direct subclasses of a sealed class are known at compile time.
No other subclasses may appear outside the module and package within which the sealed class is defined.
The same logic applies to sealed interfaces and their implementations: once a module with a sealed interface is compiled, no new implementations can be created.
When you combine sealed classes and interfaces with the when expression, you can cover the behavior of all possible subclasses and ensure that no new subclasses are created to affect your code adversely.
Sealed classes are best used for scenarios when:
Limited class inheritance is desired: You have a predefined, finite set of subclasses that extend a class, all of which are known at compile time.
Type-safe design is required: Safety and pattern matching are crucial in your project. Particularly for state management or handling complex conditional logic. For an example, check out Use sealed classes with when expressions.
Working with closed APIs: You want robust and maintainable public APIs for libraries that ensure that third-party clients use the APIs as intended.
Declare a sealed class or interface
Constructors
A sealed class itself is always an abstract class, and as a result, can't be instantiated directly.
However, it may contain or inherit constructors.
These constructors aren't for creating instances of the sealed class itself but for its subclasses.
Consider the following example with a sealed class called Error and its several subclasses, which we instantiate:
You can use enum classes within your sealed classes to use enum constants to represent states and provide additional detail.
Each enum constant exists only as a single instance, while subclasses of a sealed class may have multiple instances.
In the example, the sealed class Error along with its several subclasses, employs an enum to denote error severity. Each subclass constructor initializes the severity and can alter its state:
Constructors of sealed classes can have one of two visibilities: protected (by default) or private:
Inheritance
Direct subclasses of sealed classes and interfaces must be declared in the same package.
They may be top-level or nested inside any number of other named classes, named interfaces, or named objects.
Subclasses can have any visibility as long as they are compatible with normal inheritance rules in Kotlin.
Subclasses of sealed classes must have a properly qualified name. They can't be local or anonymous objects.
These restrictions don't apply to indirect subclasses. If a direct subclass of a sealed class is not marked as sealed, it can be extended in any way that its modifiers allow:
Use sealed classes with when expressions
The key benefit of using sealed classes comes into play when you use them in a when expression. The when expression, used with a sealed class, allows the Kotlin compiler to check exhaustively that all possible cases are covered. In such cases, you don't need to add an else clause:
Use case scenarios
TODO: