Does Kotlin have anything like discriminated unions (sum types)? What would be the idiomatic Kotlin translation of this (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

推荐答案

The common way of implementing this kind of abstraction in an OO-language (e.g. Kotlin or Scala) would be to through inheritance:

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()
}

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

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)
}

The type checker doesn't know that such a hierarchy is closed, so when you do a case-like match (when-expression) on it, it will complain that it is not exhaustive, but this will be fixed soon.

Update: while Kotlin does not support pattern matching, you can use when-expressions as smart casts to get almost the same behavior:

when (message) {
  is New -> println("new $id: $quantity")
  is Cancel -> println("cancel $id")
}

See more about smart casts here.

Kotlin相关问答推荐

用普通Kotlin理解Gradle的Kotlin DSL'""

有没有一种简单的方法来识别物体?

如何将消费者放入 Kotlin 的 map 中?

如何从 Period.between() 返回的字符串中提取信息? (Kotlin )

Kotlin中用于调用常量名称的枚举类方法之间的区别

如何使用 Firebase 和 Kotlin 在文本 (Jetpack Compose) 中显示当前用户名?

如何处理基于枚举提前返回的 forEach 循环,Kotlin 中的一条路径除外

如何使用 Either monad 并避免嵌套 flatMap

如何从 kotlin 函数中 Select 正确的枚举值

将 Gradle 子元素与 Kotlin 多平台一起使用

在 Spring Framework 5.1 中注册具有相同名称的测试 bean

如何使 TextInputEditText 只读?

Kotlin 中的数据类

在 Koin 中提供一个 Instance 作为其接口

ObserveForver是否了解生命周期?

Kotlin中OnclickListener方法之间的差异

我应该使用Kotlin数据类作为JPA实体吗?

Android Studio - java.io.IOException:无法生成 v1 签名

如何在伴随对象中使用泛型

如何在 Kotlin 中生成 MD5 哈希?