A sealed class in Kotlin is declared using the sealed
keyword before the class
keyword. The main characteristic of a sealed class is that all its sub - classes must be declared within the same file where the sealed class is declared. This restriction ensures that the set of possible sub - classes is known at compile - time.
Here is a simple example of a sealed class:
// Sealed class declaration
sealed class Shape {
// Sub - class representing a circle
class Circle(val radius: Double) : Shape()
// Sub - class representing a rectangle
class Rectangle(val width: Double, val height: Double) : Shape()
}
// Function to calculate the area of a shape
fun calculateArea(shape: Shape): Double {
return when (shape) {
is Shape.Circle -> Math.PI * shape.radius * shape.radius
is Shape.Rectangle -> shape.width * shape.height
}
}
In this example, the Shape
class is a sealed class with two sub - classes: Circle
and Rectangle
. The calculateArea
function uses a when
expression to handle each type of shape. Since the set of possible sub - classes of Shape
is known at compile - time, the when
expression doesn’t require an else
branch.
Sealed classes are often used to represent different states of an object. For example, consider a network request. It can be in one of several states: loading, success, or error.
// Sealed class to represent network request states
sealed class NetworkState {
object Loading : NetworkState()
data class Success(val data: String) : NetworkState()
data class Error(val message: String) : NetworkState()
}
// Function to handle network state
fun handleNetworkState(state: NetworkState) {
when (state) {
is NetworkState.Loading -> println("Request is loading...")
is NetworkState.Success -> println("Request succeeded with data: ${state.data}")
is NetworkState.Error -> println("Request failed with message: ${state.message}")
}
}
In this code, the NetworkState
sealed class has three sub - classes: Loading
, Success
, and Error
. The handleNetworkState
function uses a when
expression to handle each state.
Sealed classes can also be used to handle the result of an operation. For example, a function that performs a division operation can return either a successful result or an error if the divisor is zero.
// Sealed class to represent division result
sealed class DivisionResult {
data class Success(val result: Double) : DivisionResult()
object Error : DivisionResult()
}
// Function to perform division
fun divide(dividend: Double, divisor: Double): DivisionResult {
return if (divisor == 0.0) {
DivisionResult.Error
} else {
DivisionResult.Success(dividend / divisor)
}
}
// Function to handle division result
fun handleDivisionResult(result: DivisionResult) {
when (result) {
is DivisionResult.Success -> println("Division result: ${result.result}")
is DivisionResult.Error -> println("Error: Division by zero")
}
}
In this example, the divide
function returns a DivisionResult
object, which can be either a Success
or an Error
. The handleDivisionResult
function uses a when
expression to handle the result.
when
Expressions: Since the set of possible sub - classes is known, when
expressions can be used without an else
branch, which makes the code more type - safe.Kotlin sealed classes are a powerful tool for modeling a restricted set of choices in a type - safe manner. They are particularly useful for representing states, handling results, and other scenarios where the set of possible types is known at compile - time. By following the best practices, developers can write more robust and maintainable code using sealed classes.