我有一组共享某些公共(public)字段的数据类,因此理想情况下,我想在一个父类(super class)型中声明它们(在此示例中为Message),并能够编写在该父类(super class)型上操作的函数(如果它们需要访问这些公共(public)字段)字段(在此示例中为messageId)。

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

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

数据类可以扩展密封类,但是我不确定它们如何/是否可以接受“父类(super class)型”密封类所需的参数。
  • 从密封的类中扩展常规类可以很好地进行编译。
    sealed class Message(val messageId: String)
    
    class Track(val event: String, messageId: String): Message(messageId)
    
  • 但是,不能将其更改为数据类(“数据类的主要构造函数必须仅具有属性(val / var)参数。”)。
    sealed class Message(val messageId: String)
    
    data class Track(val event: String, messageId: String): Message(messageId)
    
  • 将参数声明为属性也不会编译(“'messageId'隐藏超型'Message'的成员,并且需要'override'修饰符'“)。
    sealed class Message(val messageId: String)
    
    data class Track(val event: String, val messageId: String): Message(messageId)
    
  • 打开supertype属性并在每个基类中覆盖它都可以正常编译:
    sealed class Message(open val messageId: String)
    
    data class Track(val event: String, override val messageId: String): Message(messageId)
    

  • 理想情况下,我想要接近选项2的东西-它使我可以将两个方面的优点结合在一起。

    否则,似乎我的选择要么是使用选项1手动滚动我自己的数据类功能(复制,哈希码,等于等),要么是通过使用选项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()
    

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

    10-06 13:12