Kotlin中如何优雅实现同名属性类实例间的值传递
Kotlin 跨类同名属性拷贝简化方案
你原代码里的compaion存在拼写错误,正确写法是companion,否则代码无法正常编译。针对大量重复的同名属性赋值场景,有以下几种常用实现方案,按需选择即可:
方案1:通用反射转换函数(零额外依赖,一次编写全项目复用)
写一个基于Kotlin反射的通用内联转换函数,自动匹配源对象和目标类主构造器的同名同类型参数,自动完成赋值,不用为每对类单独写转换逻辑:
import kotlin.reflect.full.memberProperties import kotlin.reflect.jvm.isAccessible inline fun <reified T : Any> Any.mapTo(): T { val targetConstructor = T::class.constructors.first() val sourcePropMap = this::class.memberProperties.associateBy { it.name } val constructorArgs = targetConstructor.parameters.associateWith { param -> val matchedProp = sourcePropMap[param.name] when { matchedProp != null && matchedProp.returnType == param.type -> { matchedProp.isAccessible = true matchedProp.get(this) } param.isOptional -> null else -> throw IllegalArgumentException("目标类属性${param.name}未匹配到源对象的对应同类型字段") } } return targetConstructor.callBy(constructorArgs.filterValues { it != null }) }
使用方式非常简单,任意对象只要属性和目标类主构造器参数名、类型匹配,就可以直接调用:
val a: A = getAFromSomewhere() val b: B = a.mapTo<B>()
注意:该方案基于运行时反射实现,存在少量性能开销,适合非高频调用的转换场景。
方案2:编译期对象映射框架(零反射开销,适合生产级项目)
如果项目中这类转换场景很多、调用频率高,推荐使用编译期生成映射代码的对象映射框架,它会在代码编译阶段自动生成和手写逻辑完全一致的属性赋值代码,没有运行时反射开销,性能和手写工厂方法完全相同。
使用时只需要定义映射接口,框架自动完成同名属性映射:
- 引入依赖后定义映射接口
@Mapper interface ModelMapper { fun aToB(a: A): B companion object { val INSTANCE: ModelMapper = Mappers.getMapper(ModelMapper::class.java) } }
- 直接调用即可
val a: A = getAFromSomewhere() val b: B = ModelMapper.INSTANCE.aToB(a)
如果存在不同名属性需要映射,只需要加@Mapping注解指定对应关系即可,不需要写全量赋值逻辑。
方案3:抽取公共属性接口(适合可修改类定义的场景)
如果多个类的重复字段完全一致,可以把公共属性抽取成顶层接口,让所有类实现该接口,转换方法可以基于公共接口编写,实现多对一/一对多的转换逻辑复用:
// 抽取公共属性接口 interface BaseModel { val value1: String val value2: String val value3: String val value4: String val value5: String } class A( override val value1: String, override val value2: String, override val value3: String, override val value4: String, override val value5: String, ) : BaseModel class B( override val value1: String, override val value2: String, override val value3: String, override val value4: String, override val value5: String, ) : BaseModel { companion object { // 所有实现BaseModel的类都可以用这个方法转B fun from(source: BaseModel) = B( value1 = source.value1, value2 = source.value2, value3 = source.value3, value4 = source.value4, value5 = source.value5, ) } }
内容的提问来源于stack exchange,提问作者ParkCheolu
相关产品推荐
相关产品推荐

