Which one should you choose?
Kotlin sealed class VS sealed interface
For those who want a short answer, use a sealed interface
over a sealed class
whenever possible. For the rest of you who want to get into more details:
1. Sealed keyword
What does sealed
keyword do?
- It limits the inheritance/implementation access to the package and module defined.
- All subclasses are known at compile time.
2. sealed class
They’re in Kotlin longer than sealed interface
hence, they’re more commonly used.
How do they work? Think of them as an open class
limited to a package. There are many valid use cases where you would want to limit yourself to inheriting from a single class only or leverage the use of init
and constructors
, this is when you want to use a sealed class
Here’s an example that uses these:
sealed class Animal(
val name: String,
val age: Int,
) {
// init and secondary constructor are unique to sealed classes
// and cannot be used in sealed interfaces
init {
println("Creating $name")
}
constructor(age: Int) : this(name = "Animal of age $age", age = age)
class OldDog : Animal(age = 16)
}
fun main() {
val oldDog: Animal = Animal.OldDog() // Creating Animal of age 16
}
3. sealed interface
You might not see them often because they’re newer than classes. They’re very similar to sealed class
es with these differences:
- No constructor
- They work like interfaces; hence, a class can implement multiple
sealed interface
s.
To be honest, those are all the differences.
Here’s an example of how you would try to reformat the previous sealed class
sealed interface Animal {
val name: String
val age: Int
class OldDog : Animal {
override val age = 16
override val name = "Animal of age $age"
// We can't define sinlge init block
// and need to add it to every subclass
init {
println("Creating $name")
}
}
}
fun main() {
val oldDog: Animal = Animal.OldDog() // Creating Animal of age 16
}
sealed interface
— has some limitations, but these limitations are usually what we want. It’s rather rare to need secondary constructors or want a shared init block for all of the subclasses. Moreover, these often introduce additional complexity, which makes the system harder to understand.
4. Which one should you choose?
In general, the best practice is to use sealed interface
whenever possible. In most situations, sealed classe
can be avoided, and unless you need it to be a class
(such as using a constructor) then go for the interface
instead.
When working in an existing codebase, you most likely will see sealed class
in use because they’re much more popular than sealed interface
(probably because sealed interface
was introduced later) whenever working in such a case, consider replacing class
with an interface
!
Thanks for reading! Please clap and follow me if you’ve learned something new! :-)