Kotlin和受歧视的工会(总和类型)

ehn*_*ark 37 algebraic-data-types discriminated-union kotlin

Kotlin有没有像歧视的工会(总和类型)?什么是惯用的Kotlin翻译(F#):

type OrderMessage =
    | New of Id: int * Quantity: int
    | Cancel of Id: int

let handleMessage msg = 
    match msg with
        | New(id, qty) -> handleNew id qty
        | Cancel(id) -> handleCxl id
Run Code Online (Sandbox Code Playgroud)

Ade*_*ack 32

Kotlinsealed class解决这个问题方法与Scala sealed classsealed trait.

示例(摘自链接的Kotlin文章):

sealed class Expr {
    class Const(val number: Double) : Expr()
    class Sum(val e1: Expr, val e2: Expr) : Expr()
    object NotANumber : Expr()
}
Run Code Online (Sandbox Code Playgroud)


And*_*lav 31

在OO语言(例如Kotlin或Scala)中实现这种抽象的常用方法是通过继承:

open class OrderMessage private () { // private constructor to prevent creating more subclasses outside
    class New(val id: Int, val quantity: Int) : OrderMessage()
    class Cancel(val id: Int) : OrderMessage()
}
Run Code Online (Sandbox Code Playgroud)

如果您愿意,可以将公共部分推送到超类:

open class OrderMessage private (val id: Int) { // private constructor to prevent creating more subclasses outside
    class New(id: Int, val quantity: Int) : OrderMessage(id)
    class Cancel(id: Int) : OrderMessage(id)
}
Run Code Online (Sandbox Code Playgroud)

类型检查器不知道这样的层次结构是关闭的,所以当你when对它进行类似案例的匹配(-expression)时,它会抱怨它并非详尽无遗,但很快就会修复.

更新:虽然科特林不支持模式匹配,可以使用 -expressions智能铸件得到几乎相同的行为:

when (message) {
  is New -> println("new $id: $quantity")
  is Cancel -> println("cancel $id")
}
Run Code Online (Sandbox Code Playgroud)

查看更多有关智能蒙上这里.

  • Kotlin现在有[密封类](https://kotlinlang.org/docs/reference/classes.html#sealed-classes),它允许您控制可能的层次结构,并让编译器检查您是否已用尽所有选项`陈述/表达.这解决了Andrey和@HRJ提到的问题. (21认同)

xur*_*dev 5

Kotlin中的密封类被设计为能够表示求和类型,因为它与Scala中的密封特征一起发生。

例:

sealed class OrderStatus {
    object Approved: OrderStatus()
    class Rejected(val reason: String): OrderStatus()
}
Run Code Online (Sandbox Code Playgroud)

当在比赛的when表达式中使用密封类时,使用密封类的主要好处就发挥了作用。

如果可以验证该语句是否涵盖所有情况,则无需在该语句中添加else子句。

private fun getOrderNotification(orderStatus:OrderStatus): String{
    return when(orderStatus) {
        is OrderStatus.Approved -> "The order has been approved"
        is OrderStatus.Rejected -> "The order has been rejected. Reason:" + orderStatus.reason
   }
}
Run Code Online (Sandbox Code Playgroud)

有几件事要牢记:

  • 在Kotlin中执行智能广播时,这意味着在此示例中,无需执行从OrderStatus到OrderStatus.Rejected的转换来访问原因属性。

  • 如果我们尚未定义拒绝情况的处理方法,则编译将失败,并且在IDE中会出现如下警告:

“何时”表达必须是详尽无遗的,请添加必要的“被拒绝”分支或“其他”分支。

  • 当它可以用作表达式或语句时。如果将其用作表达式,则满足的分支的值将成为通用表达式的值。如果用作语句,则忽略各个分支的值。这意味着仅在将分支用作表达式并使用结果时,才会发生缺少分支的编译错误。

这是我博客的链接(西班牙语),在该博客上,我有关于Kotlin示例的ADT的更完整的文章:http ://xurxodev.com/tipos-de-datos-algebraicos/