Kotlin和歧视联合(总和类型)

Kotlin和歧视联合(总和类型),kotlin,algebraic-data-types,discriminated-union,Kotlin,Algebraic Data Types,Discriminated Union,Kotlin是否有类似歧视性的联合(总和类型)?Kotlin对这个(F#)的惯用翻译是什么 在OO语言(如Kotlin或Scala)中实现此类抽象的常用方法是通过继承: open class OrderMessage private () { // private constructor to prevent creating more subclasses outside class New(val id: Int, val quantity: Int) : OrderMessage(

Kotlin是否有类似歧视性的联合(总和类型)?Kotlin对这个(F#)的惯用翻译是什么


在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")
}
请参阅有关智能强制转换的更多信息。

解决该问题的方法与

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


Kotlin中的密封类被设计成能够表示和类型,就像Scala中的密封特性一样

例如:

sealed class OrderStatus {
    object Approved: OrderStatus()
    class Rejected(val reason: String): OrderStatus()
}
当您在匹配的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
   }
}
有几件事需要记住:

  • 在Kotlin中,当执行smartcast时,这意味着在本例中,不必执行从OrderStatus到OrderStatus.Rejected的转换以访问reason属性

  • 如果我们没有定义如何处理被拒绝的案例,编译将失败,IDE中会出现如下警告:

“when”表达式必须详尽无遗,请添加必要的“is Rejected”分支或“else”分支。

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

这是我的博客(西班牙语)的链接,在这里我有一篇关于ADT的更完整的文章,其中有kotlin的例子:

Hi,谢谢你的回复!在Scala中,我将使用
密封的Trait OrderMessage
case类New(..)扩展OrderMessage
等。然后我可以对订单消息类型进行模式匹配,并以相同的类型访问它们的字段(就像上面的F#示例中那样)。我们有没有可能在Kotlin的
中尽快做到这一点@enhmark您可以做的是:。更多关于智能演员阵容的信息:@AndreyBreslav“会抱怨精疲力竭”。你忘了在那写上“不”吗?否则,我不理解你答案的这一部分。@HRJ有点是的,我didKotlin现在有了它,它允许你控制可能的层次结构,并让编译器检查你在
语句/表达式时是否用尽了
中的所有选项。这解决了Andrey和@HRJ提到的问题。
sealed class OrderStatus {
    object Approved: OrderStatus()
    class Rejected(val reason: String): OrderStatus()
}
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
   }
}