Tìm hiểu về sealed class trong kotlin

I, Sealed class

  • Sealed được dịch ra là khép kín. Do đó sealed class hiểu nôm na là class khép kín.
  • Sealed class được sử dụng để giới hạn hệ thống class: một variable có kiểu nằm trong một tập giới hạn.
  • Về mặt ý nghĩa, sealed class là phần mở rộng của enum class. Đồng thời, sealed class cũng là abstract class (mặc dù không có abstract keyword).

II, So sánh sealed class và enum class

  • Như mình đã nói ở trên, sealed class là phần mở rộng của enum class do đó nó sẽ tốt hơn enum class.
  • Giống nhau: variable có kiểu nằm trong một tập giới hạn.
  • Khác nhau:
    • Các enum constant chỉ có 1 kiểu khai báo (giống với enum class) và tồn tại như 1 instance của enum class. Các enum constant chỉ có thể nằm trong body của enum class.
    • Sealed class có thể có subclass. Các subclass của sealed class có thể khai báo theo nhiều cách khác nhau. Các subclass phải được khai báo cùng file với sealed class.
  • Ví dụ 1:
1
2
3
4
5
6
7
8
9
10
11
// Enum
enum class State(val message: String) {
SUCCESS("Success"),
ERROR(val exception: Exception) // not possible with enums
}

// Sealed class and its subclasses
sealed class Expr
data class Const(val number: Double) : Expr()
class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

III, So sánh sealed class và abstract class

  • Bản thân sealed class chính là abstract class nên nó có thể có subclass và abstract member.
  • Subclass của abstract class có thể khai báo ở bất cứ đâu. Subclass của sealed class chỉ có thể được khai báo cùng file với nó.
  • Mặc định, constructor của sealed class có visibility modifier là private.
  • Các class extend subclass của sealed class có thể được khai báo ở bất cứ đâu.
  • Lợi ích lớn nhất của sealed class so với abstract class là khi sử dụng điều kiện when: khi chúng ta cover hết tất cả trường hợp thì không cần mệnh đề else nữa.
  • Ví dụ 2:
1
2
3
4
5
6
7
8
9
10
11
sealed class Expr
data class Const(val number: Double) : Expr()
class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()

fun eval(expr: Expr): Double = when(expr) {
is Const -> expr.number
is Sum -> eval(expr.e1) + eval(expr.e2)
NotANumber -> Double.NaN
// the `else` clause is not required because we've covered all the cases
}