从Kotlin中的密封类扩展数据类 [英] Extending data class from a sealed class in Kotlin

查看:120
本文介绍了从Kotlin中的密封类扩展数据类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a set of data classes that share some common fields, So ideally I'd like to declare those in a supertype (Message in this example), and be able to write functions that operate on the supertype if they need access to these common fields (messageId in this example).

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

我试图通过从密封类扩展数据类来实现这一目标.

I tried to accomplish this by extending my data classes from a sealed class.

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

Data classes may extend sealed classes, but not I'm not sure how/if they can accept arguments required by the "supertype" sealed class.

  1. 从密封类中扩展常规类就可以了.

  1. Extending a regular class from a sealed class compiles just fine.

sealed class Message(val messageId: String)

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

  • 但是,将其更改为数据类不会编译(数据类的主构造函数必须仅具有属性(val/var)参数.").

  • However, changing it to a data class doesn't compile ("Data class primary constructor must have only property (val/var) parameters.").

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

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

  • Declaring the parameter as a property also doesn't compile ("'messageId' hides member of supertype 'Message' and needs 'override' modifier'").

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

  • 打开supertype属性并将其在每个基类中覆盖都可以正常编译:

  • Opening the supertype property and overriding it in each of the base classes compiles fine:

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

  • 理想情况下,我希望获得接近选项2的东西-它使我能够结合两个方面的优势.

    Ideally I would like something close to Option 2 - it allows me to combine the best of both worlds.

    否则,似乎我的选择要么是使用选项1来滚动我自己的数据类功能(复制,哈希码,等于等),要么是通过使用选项4来打开超类型属性来妥协.

    Otherwise, it seems my options are either handrolling my own data class functionality (copy, hashcode, equals etc) with option 1, or live with a compromise by opening up up the supertype properties with option 4.

    推荐答案

    选项3和4将导致该类两次保存messageId.一次进入新类,一次进入其超类.

    Options 3 and 4 would result in the class holding messageId twice. Once in the new class and once in its superclass.

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

    The solution is to declare but not define the variable in the superclass:

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

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

    This will make the messageId available on Message, but delegates the storage to whatever implements it.

    这篇关于从Kotlin中的密封类扩展数据类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆