Kotlin中如何类似JavaScript合并data class,避免实体转换重复字段赋值
解决方案
Kotlin 是静态强类型语言,对象结构在编译期就已确定,不存在 JavaScript 那种运行时动态合并任意对象属性的扩展运算符语法,但可以通过以下几种方案简化实体转换逻辑,消除重复赋值代码:
方案1:封装扩展转换函数(成本最低,推荐小范围使用)
利用 Kotlin 扩展函数特性,把重复的赋值逻辑封装为 API 实体类的扩展方法,仅需编写一次转换逻辑,后续所有转换场景直接调用方法即可:
// 为API实体类扩展转换为DB实体的方法 fun Explosive.toExplosiveDB(): ExplosiveDB = ExplosiveDB( id = 0, explosiveId = id, name = name, code = code, decelerationCharge = decelerationCharge ) // 后续使用时无需重复编写赋值逻辑 val explosiveFromApi: Explosive = // 接口返回的实体 val explosiveDB = explosiveFromApi.toExplosiveDB()
原理说明:Kotlin 扩展函数可以在不修改原有类定义的前提下,给类追加自定义方法,非常适合这类实体转换的场景,同时保留编译期类型检查,没有额外性能损耗。
方案2:注解处理器自动生成转换代码(适合大量实体转换的中大型项目)
如果项目中存在大量类似的 API 实体转 DB 实体的需求,可以使用编译期映射框架,只需定义转换规则,框架会自动生成赋值逻辑的实现代码,完全不需要手动编写赋值语句。
示例逻辑如下:
// 定义转换接口,标注映射规则 @Mapper interface EntityMapper { // 指定字段映射关系:将源对象的id字段赋值给目标对象的explosiveId字段 @Mapping(source = "id", target = "explosiveId") fun explosiveToDB(explosive: Explosive): ExplosiveDB }
原理说明:这类框架会在编译阶段扫描注解,自动生成接口的实现类,内部的字段赋值逻辑全部由框架生成,既消除了手写赋值的重复代码,也保留了静态类型检查,没有运行时性能损耗。
方案3:反射动态转换(不推荐,仅特殊场景使用)
如果需要实现类似 JS 那样动态合并属性的能力,可以先将源对象的属性反射读取为 Map,合并自定义字段后再反射实例化目标对象,但是这种方案会失去编译期类型校验,且存在运行时性能损耗,除非有特殊的动态需求否则不建议使用。
内容的提问来源于stack exchange,提问作者Aden Kurmanov
相关产品推荐
相关产品推荐

