KMM环境下如何在接口中实现使用实现类类型的泛型序列化方法
根因分析
你遇到的报错本质是两个问题:
- kotlinx.serialization 依赖编译期为
@Serializable类生成的序列化器,默认的encodeToString重载需要实化(reified)泛型参数才能在编译期匹配到对应序列化器,接口普通成员方法不支持实化泛型,运行时泛型擦除后无法识别this的实际类型。 @Serializable注解不会被接口继承,也无法直接在接口层要求子类标记该注解,因为对应的KSerializer实现是编译期才生成的,接口提前继承KSerializer会找不到类型实现。
解决方案1:使用实化泛型扩展函数(推荐,KMM友好)
这种方式不需要修改接口定义,完全编译期生成代码,无反射开销,完全兼容KMM全平台:
// 标记接口,仅用于约束可序列化的领域类 interface Domain // 定义实化泛型扩展函数,inline+reified会在编译期替换为实际调用类型 inline fun <reified T : Domain> T.toJSON(): String { return Json.encodeToString(this) } // 实现类正常标记@Serializable即可 @Serializable class User: Domain { val a: Int = 0 }
调用方式和普通成员方法完全一致:User().toJSON()。
解决方案2:接口约束子类提供序列化器(强制要求实现类可序列化)
如果需要把toJSON作为接口成员方法,且必须在编译期强制所有实现类都支持序列化,可以用这种方案:
import kotlinx.serialization.KSerializer import kotlinx.serialization.json.Json interface Domain<T> { // 要求子类返回自身类型的序列化器 fun serializer(): KSerializer<T> fun toJSON(): String = Json.encodeToString(serializer(), this as T) } // 实现类标记@Serializable后,编译器会自动生成静态的serializer()方法,直接返回即可 @Serializable class User: Domain<User> { val a: Int = 0 override fun serializer(): KSerializer<User> = User.serializer() }
如果实现类没有加@Serializable,就无法实现serializer()方法,编译期直接报错,刚好满足你要求所有实现类必须可序列化的需求。
原有泛型写法报错的原因
你之前写的泛型接口没有给T加reified修饰,运行时泛型擦除后encodeToString无法识别T对应的实际类类型,才会抛出Only KClass supported as classifier, got T的异常。
内容的提问来源于stack exchange,提问作者aepryus
相关产品推荐
相关产品推荐

