As Kotlin continues to grow in popularity, more and more developers are looking for ways to use it in their projects. One of the key features of Kotlin is its ability to seal classes, which allows for the creation of hierarchies of classes with restrictions.
In this article, we'll take a look at what sealing classes is and how it can be used in Kotlin projects. We'll also look at some code examples to see how sealing classes works in practice.
What are sealing classes?
Sealing classes are a way of creating hierarchies of classes with restrictions. A sealed class can only be subclassed by classes that are declared in the same file. This allows for greater control over the design of a class hierarchy, and can lead to more robust and reliable code.
Why use sealing classes?
There are several reasons why you might want to use sealing classes in your Kotlin code:
You can use sealing classes to create a hierarchy of classes with restricted access. This can be useful for creating API libraries, where you only want certain classes to be accessible to developers.
Sealing classes can make your code more robust and reliable. By restricting the way a class can be subclassed, you can avoid unexpected behaviour and errors in your code.
Sealing classes can make your code more concise. By sealing a class, you can avoid repeating code in multiple subclasses.
How do I use sealing classes?
To use sealing classes in your Kotlin code, you need to do two things:
sealed class Shape {
}
class Circle: Shape() {
}
You can also declare sealed classes with parameters:
sealed class Shape(val name: String) {
}
class Circle: Shape("circle") {
}
If you try to declare a subclass of a sealed class in a different file, you'll get an error:
// Error: Cannot subclass sealed class Shape
class Square: Shape() {
}
You can get around this by using a companion object:
class Square: Shape() {
companion object : Shape() {
}
}
Another way to use sealing classes is to declare them as abstract:
abstract sealed class Shape {
}
class Circle: Shape() {
}
class Square: Shape() {
}
This allows you to define abstract methods in your sealed class, which must be implemented in subclasses:
abstract sealed class Shape {
abstract fun getArea(): Double
}
class Circle(val radius: Double): Shape() {
override fun getArea(): Double {
return Math.PI * radius * radius
}
}
class Square(val side: Double): Shape() {
override fun getArea(): Double {
return side * side
}
}
You can also use sealed classes to create enums:
sealed class Shape {
class Circle(val radius: Double): Shape()
class Square(val side: Double): Shape()
}
fun getArea(shape: Shape): Double {
return when(shape) {
is Shape.Circle -> Math.PI * shape.radius * shape.radius
is Shape.Square -> shape.side * shape.side
}
}
This allows you to create an enum with arbitrary data:
enum class Shape(val name: String) {
CIRCLE("circle"),
SQUARE("square")
}
You can also use sealed classes to create sealed objects:
sealed class Shape {
object Circle: Shape()
object Square: Shape()
}
fun getArea(shape: Shape): Double {
return when(shape) {
is Shape.Circle -> Math.PI * 1.0 * 1.0
is Shape.Square -> 1.0 * 1.0
}
}
Sealed objects are a type of singleton, which means there can only be one instance of the object in memory. This can be useful for creating things like caches or thread pools.
If you try to create a second instance of a sealed object, you'll get an error:
// Error: Object 'Shape.Circle' has already been created
val circle = Shape.Circle
You can find more information about sealed classes in the Kotlin documentation:
https://kotlinlang.org/docs/reference/sealed-classes.html
And you can find more information about singletons in the Kotlin documentation:
https://kotlinlang.org/docs/reference/object-declarations.html#object-declarations
In summary, sealing classes is a way of creating hierarchies of classes with restrictions. Sealing classes can be useful for creating API libraries, where you only want certain classes to be accessible to developers. Sealing classes can also make your code more robust and reliable.