如何将Kotlin中的类继承与Kotlinx序列化结合使用



我有一个简单的层次结构,包含以下内容:

  • 抽象类BaseItem
  • 打开类项目:BaseItem
  • class背包:物品

它们都应该使用Kotlinx序列化。直到我添加了Backpack类,一切都很顺利。我使用Kotlinx序列化的1.4.32版本。

这是我的类层次结构的详细

// Items.kt
@Serializable
sealed class BaseItem {
abstract val id: String
abstract val type: ItemType
abstract var brand: String
abstract var model: String
abstract var imageLink: String
abstract var traits: MutableList<Trait>
abstract var implicitTraits: MutableList<Trait>
abstract var details: MutableMap<String, String>
}
@Serializable
open class Item(
override val id: String = UUID.randomUUID().toString(),
override val type: ItemType = ItemType.UNDEFINED,
override var brand: String,
override var model: String,
override var imageLink: String,
override var traits: MutableList<Trait>,
override var implicitTraits: MutableList<Trait>,
override var details: MutableMap<String, String>,
) : BaseItem()
@Serializable // is marked as incorrect 
class Backpack(
brand: String,
model: String,
imageLink: String,
traits: MutableList<Trait>,
implicitTraits: MutableList<Trait>,
details: MutableMap<String, String>,
var volume: Int
) : Item(
type = ItemType.BACKPACK,
brand = brand,
model = model,
imageLink = imageLink,
traits = traits,
implicitTraits = implicitTraits,
details = details
)

IDE为Backpack类附加的@Serialization注释显示了以下消息。

This class is not serializable automatically because it has primary constructor parameters that are not properties

我无法找到正确的工作方法

这是因为构造函数的参数没有定义为类的属性。要将参数定义为特性,必须将valvar添加到参数中。这将解决您当前的错误消息:
@Serializable
class Backpack(
override var brand: String,
override var model: String,
override var imageLink: String,
override var traits: MutableList<Trait>,
override var implicitTraits: MutableList<Trait>,
override var details: MutableMap<String, String>,
var volume: Int
) : Item(
type = ItemType.BACKPACK,
brand = brand,
model = model,
imageLink = imageLink,
traits = traits,
implicitTraits = implicitTraits,
details = details
)

但这仍然不会编译,因为您最终会为两个类中使用的所有属性使用Serializable class has duplicate serial name of property 'brand', either in the class itself or its supertypes。但无论如何,我对这个设计有点惊讶,因为从非抽象类继承通常不是一个好的实践。在不知道意图的情况下,我想知道这样的sth是否对你也不起作用:

sealed class BaseItem {
abstract val id: String
abstract val type: ItemType
abstract var brand: String
abstract var model: String
abstract var imageLink: String
abstract var traits: MutableList<Trait>
abstract var implicitTraits: MutableList<Trait>
abstract var details: MutableMap<String, String>
}
@Serializable
data class Item(
override val id: String = UUID.randomUUID().toString(),
override val type: ItemType = ItemType.UNDEFINED,
override var brand: String,
override var model: String,
override var imageLink: String,
override var traits: MutableList<Trait>,
override var implicitTraits: MutableList<Trait>,
override var details: MutableMap<String, String>,
) : BaseItem()
@Serializable
data class Backpack(
override val id: String = UUID.randomUUID().toString(),
override val type: ItemType = ItemType.BACKPACK,
override var brand: String,
override var model: String,
override var imageLink: String,
override var traits: MutableList<Trait>,
override var implicitTraits: MutableList<Trait>,
override var details: MutableMap<String, String>,
override var var volume: Int
) : BaseItem()

顺便说一句,我从BaseItem中删除了@Serializable,因为它是不必要的,因为该类无论如何都是抽象的,因此根本不会序列化。我还制作了data class类,因为我的印象是,这些类基本上是用来保存数据的,并且通常是用data class实现的。我留下了我看到的许多var,因为我不知道它们的原因,但我这边的一个小提示是,你应该更喜欢val而不是var,尤其是在data class中。在这种情况下,var对我来说就像是一种代码气味,您可能需要考虑使用val。Kotlin页面本身就是一个很好的文本:https://kotlinlang.org/docs/coding-conventions.html#idiomatic-语言功能的使用

从设计可序列化层次结构:

要使类的层次结构可序列化,父类中的属性必须标记为抽象,使〔parent〕类也是抽象的。

最新更新