sealed class và sealed interface trong Kotlin là các cơ chế phân cấp kiểu giới hạn, nơi tất cả các lớp con có thể có đều được biết tại thời điểm biên dịch. Không giống như các lớp trừu tượng thông thường, sealed class đảm bảo xử lý đầy đủ tất cả các biến thể trong biểu thức when. Theo tài liệu JetBrains Kotlin Language Guide (2026), các kiểu sealed là nền tảng để mô hình hóa trạng thái, màn hình UI và các kiểu kết quả trong các dự án Kotlin.
Những điểm chính
sealed class là một lớp trừu tượng với một hạn chế: tất cả các lớp con trực tiếp của nó phải được khai báo trong cùng tệp với chính lớp sealed đó. Hạn chế này làm cho hệ thống phân cấp trở nên kín (sealed) — không có mã nào bên ngoài tệp có thể thêm lớp con mới.
sealed interface, được thêm vào Kotlin 1.5, cung cấp cùng một đảm bảo nhưng với tính linh hoạt của một interface: một sealed interface có thể được triển khai bởi nhiều lớp, đối tượng hoặc các interface khác trong một tệp. Không giống như sealed class, sealed interface không có hạn chế kế thừa đơn — một lớp có thể triển khai nhiều sealed interface cùng lúc.
Theo Kotlin Evolution and Roadmap (2026), sealed interface được thêm vào theo yêu cầu của cộng đồng để mô hình hóa linh hoạt hơn. Động lực chính là khả năng kết hợp các hệ thống phân cấp kiểu độc lập mà không cần kế thừa nhiều lớp.
Việc khai báo một sealed class bắt đầu bằng từ khóa sealed trước class. Các lớp con được khai báo trong cùng tệp.
sealed class NetworkResult {
data class Success(val data: String) : NetworkResult()
data class Error(val message: String) : NetworkResult()
object Loading : NetworkResult()
}
Mỗi lớp con của một sealed class có thể có các thuộc tính và phương thức riêng. Loading là một singleton (object), Success và Error là các data class với tham số. Trình biên dịch biết cả ba biến thể và kiểm tra tính đầy đủ của chúng khi được sử dụng trong when.
Các lớp sealed có thể được lồng vào nhau, tạo ra các hệ thống phân cấp đa cấp cho các mô hình dữ liệu phức tạp mà không mất an toàn kiểu.
sealed class UiState {
object Idle : UiState()
object Loading : UiState()
data class Content(val items: List<Item>) : UiState()
data class Error(val exception: Throwable) : UiState()
}
sealed interface được khai báo tương tự như sealed class, nhưng cho phép triển khai nhiều sealed interface trong một lớp.
sealed interface Action
sealed interface Loggable
data class Navigate(val route: String) : Action, Loggable
data class ShowToast(val text: String) : Action
object GoBack : Action, Loggable
Lớp Navigate triển khai hai sealed interface cùng lúc — Action và Loggable. Điều này không thể thực hiện được với sealed class do hạn chế kế thừa đơn. sealed interface cung cấp tính linh hoạt để kết hợp các hệ thống phân cấp độc lập.
sealed interface được ưu tiên khi hệ thống phân cấp không yêu cầu trạng thái chia sẻ hoặc hàm tạo. Theo JetBrains Kotlin Guidelines (2026), sealed interface nên được sử dụng theo mặc định cho tất cả các hệ thống phân cấp mới nơi không cần hàm tạo chung, giúp mã linh hoạt hơn cho các mở rộng trong tương lai.
Lợi thế chính của các kiểu sealed là xử lý đầy đủ (exhaustive) trong biểu thức when. Trình biên dịch kiểm tra rằng tất cả các lớp con có thể có đều được bao phủ.
fun handleResult(result: NetworkResult): String = when (result) {
is NetworkResult.Success -> "Data: ${result.data}"
is NetworkResult.Error -> "Error: ${result.message}"
is NetworkResult.Loading -> "Loading..."
// else là không bắt buộc — trình biên dịch biết rằng tất cả các biến thể đã được bao phủ
}
Nếu một nhà phát triển thêm một lớp con mới vào hệ thống phân cấp sealed nhưng quên xử lý nó trong when — trình biên dịch sẽ báo lỗi. Đây là sự an toàn ở cấp độ kiểu, không có sẵn với các hệ thống phân cấp mở sử dụng nhánh else.
Theo Google Android Developers (2026), các lớp sealed là cách được khuyến nghị để mô hình hóa trạng thái UI trong Jetpack Compose. Kiểm tra đầy đủ của when ngăn chặn các trạng thái nơi nhà phát triển chưa xử lý tất cả các biến thể hiển thị có thể có của một màn hình.
enum class và sealed class thường bị nhầm lẫn, nhưng chúng có mục đích và khả năng khác nhau.
| Đặc điểm | sealed class | enum class |
|---|---|---|
| Thể hiện | Nhiều (data class), một (object) | Chính xác một mỗi hằng số |
| Thuộc tính | Khác nhau cho mỗi lớp con | Giống nhau cho tất cả hằng số |
| Kế thừa | Có (từ sealed class) | Không (ngầm final) |
| Hàm tạo | Có thể có tham số | Chỉ chia sẻ cho tất cả hằng số |
| Phân cấp | Giới hạn, sealed | Tập hằng số cố định |
Việc lựa chọn giữa sealed class và enum class phụ thuộc vào nhiệm vụ. Nếu các biến thể không mang dữ liệu bổ sung — hãy sử dụng enum. Nếu mỗi biến thể chứa các trường duy nhất — hãy sử dụng sealed class hoặc sealed interface.
Các kiểu sealed được sử dụng trong các dự án Kotlin cho một loạt các kịch bản tiêu chuẩn nơi cần mô hình hóa an toàn kiểu.
Mỗi màn hình Compose có thể có một sealed class UiState mô tả tất cả các trạng thái có thể: Idle, Loading, Content(data), Error(exception). Biểu thức when đảm bảo rằng tất cả các trạng thái đều được xử lý.
NetworkResult với các biến thể Success, Error, Loading là một mẫu tiêu chuẩn trong các dự án Kotlin sử dụng Retrofit và Ktor. sealed class đảm bảo xử lý an toàn mỗi kết quả yêu cầu.
sealed interface cho các tuyến điều hướng cho phép các mô-đun khai báo tuyến riêng của chúng trong khi vẫn nằm trong một hệ thống phân cấp thống nhất. Điều này loại bỏ các lỗi với các tuyến không xác định tại thời điểm biên dịch.
Theo KotlinConf (2025), sealed class và sealed interface là nền tảng của thiết kế an toàn kiểu trong các ứng dụng Kotlin hiện đại. Chúng kết hợp với data class để mô hình hóa các cấu trúc miền phức tạp mà không mất an toàn tại thời điểm biên dịch.
Câu hỏi thường gặp
Tất cả các lớp con trực tiếp của một sealed class phải được khai báo trong cùng tệp. Đối với sealed interface cũng áp dụng quy tắc tương tự — triển khai trong một tệp.
Không, quy tắc một tệp cũng áp dụng cho sealed interface. Tất cả các triển khai phải nằm trong tệp nơi sealed interface được khai báo.
sealed interface không có trạng thái hoặc hàm tạo và cho phép triển khai nhiều lần. sealed class có thể có hàm tạo và trạng thái chia sẻ, nhưng một lớp chỉ có thể kế thừa một sealed class.
Trình biên dịch kiểm tra tính đầy đủ của when: nếu không phải tất cả các lớp con đều được xử lý, mã sẽ không biên dịch. Điều này loại bỏ lỗi thời gian chạy và làm cho mã an toàn hơn.
Có, một sealed class có thể có hàm tạo (mặc định là private). Tất cả các lớp con có thể truyền tham số cho hàm tạo này thông qua super().
Tóm tắt
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm