Summary: Sealed interfaces in Kotlin define closed hierarchies without sealed class boilerplate, enabling flexible, compile-time exhaustiveness checks across multiple implementations. Value classes (@JvmInline value class) wrap single properties without runtime allocation, improving performance and type safety through domain-specific primitive type contexts. The combination of sealed interfaces with value classes creates expressive, zero-overhead domain models while maintaining exhaustive when coverage and avoiding object allocations.

Sealed Classes vs. Sealed Interfaces

Sealed classes and interfaces restrict subclassing to known sets within the same module, enabling compiler exhaustiveness checks in when expressions. Sealed classes support state and constructors, while sealed interfaces lack constructor parameters and maintain implicit public members, making interfaces suitable for scenarios without shared state requirements.

Sealed Interface Implementation Patterns

Sealed interfaces excel in modeling behaviors across unrelated types, defining interfaces like ScreenState implemented by both UI and background states without requiring common base classes. In Android applications, sealed interfaces frequently replace sealed classes for state machines or event streams, reducing overhead when shared properties are unnecessary.

Value Class Performance Analysis

Value classes eliminate wrapper allocations through compile-time property inlining, avoiding heap objects and improving performance in critical paths. They enforce domain-specific types by wrapping primitives like String or Int, preventing unit or identifier mixing while enhancing code clarity and safety.

Combined Implementation Strategy

Sealed interfaces as parents of multiple value classes create exhaustive, zero-overhead hierarchies:

sealed interface Measurement
@JvmInline value class Meters(val value: Double) : Measurement
@JvmInline value class Seconds(val value: Long) : Measurement

This pattern models distinct units under a single type, with when expressions on Measurement covering all cases at compile time without wrapper object allocations.

Performance Impact Analysis

Measurement formatting functions demonstrate the performance benefits:

fun format(m: Measurement) = when(m) {
  is Meters  -> "${m.value} m"
  is Seconds -> "${m.value} s"
}

The Kotlin compiler eliminates wrapper allocations for Meters and Seconds, inlining primitive values directly. Benchmark results indicate inline value classes reduce memory pressure by up to 90% compared to data classes, with minimal impact on method dispatch performance.

Conclusion

Sealed interfaces and value classes provide a powerful combination for building concise, type-safe APIs in Kotlin, guaranteeing exhaustiveness, preventing invalid states, and eliminating runtime overhead. These patterns enable robust domain modeling and high-performance code in Android applications.