kotlin - 有什么方法可以要求在 kotlin 中的类型参数上添加注释吗?

标签 kotlin generics kotlinx.serialization

我正在制作一个自动将数据保存到磁盘的数据结构。为此,我使用 kotlinx-serialization。有没有办法要求泛型类型具有@Serializabe注释?

class PersistentList <@Serializable E> () : List<E> {...}

该示例无法编译。希望你明白我的意思。我想限制 E 有注释。有办法做到吗?

最佳答案

KSerializer构造函数参数

您可以添加KSerializer对于 EPersistentList 的构造函数中.

class PersistentList<E>(
    elementSerializer: KSerializer<E>
) : List<E> { 
  // ... 
}

虽然更详细,但它比向 E 添加注释更有优势。 - 可以分配自定义序列化程序,这意味着 PersistentList可能包含来自外部代码但没有 @Serializable 的类注释。

import kotlinx.serialization.KSerializer

// Assume this class is from another library, meaning @Serializable cannot be added
data class SomeExternalData(
  val name: String
}

// Create a custom serializer for SomeExternalData
object SomeExternalDataSerializer : KSerializer<SomeExternalData> {
  // ...
}

fun main() {
  // Since a serializer is required, the `E` must be serializable
  val persistentList = PersistentList(SomeExternalDataSerializer)
}


class PersistentList< E: PersistentElement>(
  elementSerializer: KSerializer<E>,
) : List<E> {
  // ...
}

这是确保 E 的唯一可行方法是可序列化的。即使是注释也无法做到这一点!

SerializersModule.serializer()

为了使其更加自动化,您可以使用 SerializersModule ,它有一个函数 serializer() ,可以通过反射魔法获取序列化器。

可以创建一个类似于 Json.encodeToString(...) 的扩展函数,这将自动确定特定格式的序列化器。

/** Automatically determine the serializable type of [PersistentList] */
inline fun <reified T> SerialFormat.createPersistentList(): PersistentList<SomeData> =
    PersistentList(serializersModule.serializer())

但是,这不会触发任何编译时检查。

这是一个更完整的示例:

import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialFormat
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.serializer

@Serializable
data class SomeData(
  val name: String
)

fun main() {
  val persistentList = Json.createPersistentList(listOf(
      SomeData("1"), SomeData("2"), SomeData("3"),
    ))

  println(persistentList)

  val encoded = Json.encodeToString(persistentList.listSerializer, persistentList.actualList)

  println(encoded)
}

class PersistentList<E>(
  elementSerializer: KSerializer<E>,
  val actualList: List<E>,
) : List<E> by actualList {
  val listSerializer = ListSerializer(elementSerializer)
}


inline fun <reified E> SerialFormat.createPersistentList(actualList: List<E>): PersistentList<E> =
  PersistentList(serializersModule.serializer(), actualList)

关于kotlin - 有什么方法可以要求在 kotlin 中的类型参数上添加注释吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74604364/

相关文章:

java - Kotlin:从 Java 类访问公共(public)字段,该类也覆盖同名的公共(public) getter

kotlin - 从列表中收集偶数到奇数元素以在 Kotlin 中进行映射的惯用方法

java - Mockito:使用有界通配符返回类型的 stub 方法

json - kotlinx 序列化——进行多态子反序列化的最佳方式

java - kotlin - 平台类型/方法的非空标记

android - BottomSheetDialogFragment 未显示

c# - 是否为 DbSet 启用了删除级联?

java - 如何创建通用原始数组?

gradle - Gradle无法找到用于Kotlinx序列化的Bintray存储库

kotlin - 如何禁用 kotlinx 序列化多态鉴别器?