从Kotlin中的密封类扩展数据类

从Kotlin中的密封类扩展数据类,kotlin,data-class,sealed-class,Kotlin,Data Class,Sealed Class,我有一组共享一些公共字段的数据类,因此理想情况下,我希望在超类型(本例中为Message)中声明这些数据类,并且如果需要访问这些公共字段(本例中为messageId),则能够编写在超类型上操作的函数 我试图通过从一个密封的类扩展我的数据类来实现这一点 数据类可以扩展密封类,但我不确定它们如何/是否可以接受“超类型”密封类所需的参数 从一个密封类扩展一个常规类就可以编译了 sealed class Message(val messageId: String) class Track(val ev

我有一组共享一些公共字段的数据类,因此理想情况下,我希望在超类型(本例中为Message)中声明这些数据类,并且如果需要访问这些公共字段(本例中为messageId),则能够编写在超类型上操作的函数

我试图通过从一个密封的类扩展我的数据类来实现这一点

数据类可以扩展密封类,但我不确定它们如何/是否可以接受“超类型”密封类所需的参数

  • 从一个密封类扩展一个常规类就可以编译了

    sealed class Message(val messageId: String)
    
    class Track(val event: String, messageId: String): Message(messageId)
    
  • 但是,将其更改为数据类不会编译(“数据类主构造函数必须只有属性(val/var)参数”)

  • 将参数声明为属性也不会编译(“'messageId'隐藏超类型'Message'的成员,需要'override'修饰符'”)

  • 打开supertype属性并在每个基类中重写它可以很好地编译:

    sealed class Message(open val messageId: String)
    
    data class Track(val event: String, override val messageId: String): Message(messageId)
    
  • 理想情况下,我想要接近选项2的东西——它允许我将两个世界的优点结合起来


    否则,我的选项似乎要么使用选项1来处理我自己的数据类功能(复制、hashcode、equals等),要么通过使用选项4打开超类型属性来进行折衷。

    选项3和4将导致类持有
    messageId
    两次。一次在新类中,一次在其超类中

    解决方案是在超类中声明但不定义变量:

    sealed class Message {
        abstract val messageId: String
    }
    
    data class Track(val event: String, override val messageId: String): Message()
    

    这将使messageId在
    Message
    上可用,但将存储委托给实现它的任何对象。

    扩展数据类必须嵌套在密封的超类中还是仅嵌套在同一个文件中@阿尔瓦罗似乎是这样,看起来只有正常的密封类限制适用。
    sealed class Message(val messageId: String)
    
    data class Track(val event: String, val messageId: String): Message(messageId)
    
    sealed class Message(open val messageId: String)
    
    data class Track(val event: String, override val messageId: String): Message(messageId)
    
    sealed class Message {
        abstract val messageId: String
    }
    
    data class Track(val event: String, override val messageId: String): Message()