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

我有一组共享一些公共(public)字段的数据类,所以理想情况下,我想在父类(super class)型中声明它们(本例中为 Message),并且能够编写在需要访问时对父类(super class)型进行操作的函数到这些公共(public)字段(本例中为 messageId)。

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

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

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

  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' 隐藏父类(super class)型'Message'的成员并需要'override'修饰符'”)。

    sealed class Message(val messageId: String)
    
    data class Track(val event: String, val messageId: String): Message(messageId)
    
  4. 打开父类(super class)型属性并在每个基类中覆盖它可以正常编译:

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

理想情况下,我想要接近选项 2 的东西 - 它可以让我结合两全其美。

否则,我的选择似乎是使用选项 1 手动处理我自己的数据类功能(复制、哈希码、equals 等),或者通过使用选项 4 打开父类(super class)型属性来妥协。

最佳答案

选项 3 和 4 将导致类持有 messageId 两次。一次在新类中,一次在其父类(super class)中。

解决方法是在父类(super class)中声明但不定义变量:

sealed class Message {
    abstract val messageId: String
}

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

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

https://stackoverflow.com/questions/44419997/

相关文章:

android - 使用 Kotlin 关闭/隐藏 Android 软键盘

kotlin - 如何在一行上声明多个属性

android - Kotlin 错误 : Dagger does not support inje

android - 使用 Kotlin 组合整数标志的最佳方法?

kotlin - 如何在 Kotlin 中定义非序数枚举?

android - 从 Activity Kotlin 中获取额外的字符串

kotlin - 为什么这个 Kotlin 方法有封闭的反引号?

kotlin - 在 Kotlin 中复制 map 最聪明的方法是什么?

android - 使用 Retrofit 方法更具表现力

kotlin - 做任何==对象