从Kotlin中的密封类扩展数据类 [英] Extending data class from a sealed class in 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.
-
从密封类中扩展常规类就可以了.
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屋!