DEV Community

deniz
deniz

Posted on

Sealed Classes: Modern Class Grouping

Previously, class inheritance (inheritance) was used to establish hierarchies and group certain classes. However, with sealed classes, we can now create more controlled and restricted class hierarchies. Using sealed classes transfers the control of the class hierarchy from the developer to the IDE and compiler. This approach makes the code more secure and manageable.

When to Use Sealed Classes:
Limited Class Inheritance is Desired: By limiting the class hierarchy, you can prevent inheritance from expanding in unwanted directions. This is useful when you want to control and restrict the behavior of a class. One of the advantages of sealed classes is that all subclasses are known at compile time. This allows the compiler to perform comprehensive security checks. If a new subclass needs to be added, it should be defined and used within the same module.

Type-Safe Design is Required: Type-safety ensures that a variable is of the expected type and does not perform operations outside that type. With sealed classes, you can ensure this safety in when expressions. The compiler, knowing all possible types, can perform logical checks covering all possible cases. The when statement handles all possible types of a sealed class. The compiler checks if all cases are covered and warns you if a type is missing, ensuring your application is type-safe.

Working with Closed APIs: Closed APIs are those offered to the outside world but can only be used with certain constraints. In such APIs, your classes may need to be extended in certain ways, but you want to prevent them from being extended in ways you don’t trust or want. Sealed classes provide this control. By using sealed classes, you can ensure that external developers use your API only through the subclasses you specify. This prevents your API from being used in incorrect or unexpected ways. Additionally, future updates to your API can be managed more easily and in a controlled way with sealed classes since they allow your API to work with only a specific set of subclasses.

Summary:
Limited Class Inheritance: Sealed classes limit class inheritance, allowing only specified subclasses to be extended.

Type-Safe Design: Increases type safety by securely controlling all possible subclasses, reducing the likelihood of errors.

Working with Closed APIs: Sealed classes limit class usage in API design, preventing unwanted extensions from external sources and ensuring the API is used securely and sustainably.

Object Creation and Constructors:
A sealed class is always abstract and therefore cannot be instantiated directly. However, it can contain constructors or inherit them. These constructors are intended for subclasses, not for creating instances of the sealed class itself. Constructors can have one of two visibility modifiers: protected (by default) or private. If desired, a secondary constructor can be added.

Image description

Sealed Classes and Inheritance:
Sealed classes can inherit from another class. This class can be open, sealed, or abstract; this does not prevent sealed classes from inheriting.

Image description

Sealed class subclasses must be defined within the same file. That is, sealed classes can only be inherited within the same file. Interfaces work seamlessly with sealed classes. If an interface contains functions without a body, these functions must be either defined within the sealed class implementing that interface or overridden by all subclasses extending that sealed class.

Companion Object:
A companion object can be defined within a sealed class or sealed interface and shared by all subclasses of the sealed class.

Versatility of Sealed Classes:
Direct subclasses of sealed classes behave statically within the boundaries of the sealed class but are not actually static, so their objects can be created. These direct subclasses inherit the sealed class, so they cannot inherit from another class. Kotlin does not support multiple inheritance; however, sealed classes can implement an interface, giving them versatility.

Sealed Classes vs. Enum Classes:
Enum Use Case: When constants share common features and must exhibit the same behavior, and only a single instance is needed.

Sealed Class Use Case: When each constant can have different features and behave independently, when subclasses need open inheritance, when multiple instances need to be produced, and when constants need to directly use class features (e.g., data class), or when a class needs to be inherited by another class.

Conclusion:
Sealed classes offer a powerful tool for managing class hierarchies in a secure and flexible way in Kotlin. This structure increases code security while providing developers with controlled extensibility, offering an excellent solution for scenarios requiring type safety, error management, and state control. The primary advantage of sealed classes is that their subclasses are known at compile time, increasing code predictability, reducing potential errors, and allowing for the comprehensive handling of all possible cases in when expressions, enabling the writing of more robust and reliable code. Consequently, sealed classes significantly contribute to Kotlin's object-oriented programming paradigm by enhancing code readability, maintainability, and security, thereby aiding in the development of higher-quality and more sustainable software.

Top comments (0)