Подтвердить что ты не робот

Котлин и дискриминационные союзы (типы сумм)

Есть ли у Котлина что-то вроде дискриминационных союзов (типы сумм)? Каким будет идиоматический перевод Котлина этого (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
4b9b3361

Ответ 1

Общим способом реализации такого вида абстракции в 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()
}

Вы можете нажать общую часть на суперкласс, если хотите:

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

Средство проверки типов не знает, что такая иерархия закрыта, поэтому, когда вы выполняете случайное совпадение (when -expression), оно будет жаловаться, что оно не является исчерпывающим, но это будет исправлено в ближайшее время.

Обновление:, в то время как Kotlin не поддерживает сопоставление шаблонов, вы можете использовать при -выражения как умные приведения, чтобы получить почти то же поведение:

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

Подробнее о умных приведениях здесь.

Ответ 2

Kotlin sealed class подход к этой проблеме чрезвычайно похож на Scala sealed class.

https://kotlinlang.org/docs/reference/sealed-classes.html

Пример (из этой ссылки):

sealed class Expr {
    class Const(val number: Double) : Expr()
    class Sum(val e1: Expr, val e2: Expr) : Expr()
    object NotANumber : Expr()
}