从Kotlin的密封类扩展数据类

我有一组数据类共享一些共同的领域,所以理想情况下,我想声明这些超类型(在这个例子中的消息),并能够编写的功能,操作超类型,如果他们需要访问这些常见字段(在这个例子中是messageId)。

fun operate(m: Message) { use(m.messageId) } 

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

数据类可以扩展密封类,但不是我不知道如何/如果他们可以接受“超类型”密封类所需的参数。

  1. 从一个密封的类扩展一个普通的类编译就好了。

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

     sealed class Message(val messageId: String) data class Track(val event: String, messageId: String): Message(messageId) 
  3. 声明参数作为属性也不会编译(“'messageId'隐藏超类型'消息'的成员,并需要'覆盖'修饰符'”)。

     sealed class Message(val messageId: String) data class Track(val event: String, val messageId: String): Message(messageId) 
  4. 打开超类型属性,并在每个基类中重写它编译罚款:

     sealed class Message(open val messageId: String) data class Track(val event: String, override val messageId: String): Message(messageId) 

理想情况下,我想要接近选项2 – 它允许我结合两全其美。

否则,看起来我的选择是用选项1来滚动我自己的数据类功能(复制,散列码,等于等等),或者用选项4打开超类型属性来折中妥协。

选项3和4将导致该类持有messageId两次。 一旦进入新班级,一次进入超班。

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

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

这将使MessageId在Message可用,但是将存储委托给实现它的任何东西。