Sealed Class trong Kotlin
1. Giới thiệu
Sealed class giới hạn các subclasses có thể có, hữu ích cho representing restricted hierarchies.
2. Khai báo Sealed Class
sealed class Result {
data class Success(val data: String) : Result()
data class Error(val message: String) : Result()
object Loading : Result()
}
fun handleResult(result: Result) {
when (result) {
is Result.Success -> println("Data: ${result.data}")
is Result.Error -> println("Error: ${result.message}")
Result.Loading -> println("Loading...")
}
}3. when Exhaustive
sealed class Color {
object Red : Color()
object Green : Color()
object Blue : Color()
}
fun getColorCode(color: Color): String {
// Không cần else vì đã cover hết
return when (color) {
Color.Red -> "#FF0000"
Color.Green -> "#00FF00"
Color.Blue -> "#0000FF"
}
}4. Sealed với Data Class
sealed class ApiResponse<out T> {
data class Success<T>(val data: T) : ApiResponse<T>()
data class Error(val code: Int, val message: String) : ApiResponse<Nothing>()
object Loading : ApiResponse<Nothing>()
}
fun <T> handleResponse(response: ApiResponse<T>) {
when (response) {
is ApiResponse.Success -> println("Got: ${response.data}")
is ApiResponse.Error -> println("Error ${response.code}: ${response.message}")
ApiResponse.Loading -> println("Loading...")
}
}5. Nested Sealed Classes
sealed class UIState {
object Idle : UIState()
object Loading : UIState()
sealed class Loaded : UIState() {
data class Success(val data: List<String>) : Loaded()
data class Empty(val message: String) : Loaded()
}
data class Error(val exception: Throwable) : UIState()
}6. Sealed Interface (Kotlin 1.5+)
sealed interface Error
class IOError(val message: String) : Error
class NetworkError(val code: Int) : Error
object UnknownError : Error
fun handle(error: Error) = when (error) {
is IOError -> println("IO: ${error.message}")
is NetworkError -> println("Network: ${error.code}")
UnknownError -> println("Unknown error")
}7. State Machine với Sealed Class
sealed class PlayerState {
object Idle : PlayerState()
data class Playing(val position: Int) : PlayerState()
data class Paused(val position: Int) : PlayerState()
object Stopped : PlayerState()
}
class MusicPlayer {
var state: PlayerState = PlayerState.Idle
fun play() {
state = when (val current = state) {
PlayerState.Idle -> PlayerState.Playing(0)
is PlayerState.Paused -> PlayerState.Playing(current.position)
else -> state
}
}
}8. So sánh với Enum
// Enum - mỗi instance giống nhau
enum class Color { RED, GREEN, BLUE }
// Sealed class - mỗi subclass có structure khác nhau
sealed class Shape {
data class Circle(val radius: Double) : Shape()
data class Rectangle(val w: Double, val h: Double) : Shape()
}9. Ví dụ thực tế: Network Response
sealed class NetworkResult<out T> {
data class Success<T>(val data: T) : NetworkResult<T>()
data class HttpError(val code: Int, val body: String?) : NetworkResult<Nothing>()
data class NetworkError(val exception: Exception) : NetworkResult<Nothing>()
}
suspend fun fetchUser(): NetworkResult<User> {
return try {
val response = api.getUser()
if (response.isSuccessful) {
NetworkResult.Success(response.body()!!)
} else {
NetworkResult.HttpError(response.code(), response.errorBody()?.string())
}
} catch (e: Exception) {
NetworkResult.NetworkError(e)
}
}📝 Tóm tắt
sealed classgiới hạn subclasses- Tất cả subclasses định nghĩa trong cùng file
whenexhaustive - không cầnelse- Kết hợp với data class cho rich data
- Phù hợp cho state machines, error handling
- Sealed interface từ Kotlin 1.5+
Last updated on