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

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

Общим способом реализации такого вида абстракции на языке 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 не поддерживает сопоставление шаблонов , вы можете использовать, когда -expressions как умные приведения, чтобы получить почти то же поведение:

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

Подробнее о умных переводах читайте здесь .

Заключенный подход Котлина к этой проблеме очень похож на sealed class Scala.

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