在Kotlin中合并/合并数据类 [英] Combining/merging data classes in Kotlin

查看:2201
本文介绍了在Kotlin中合并/合并数据类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在不指定所有属性的情况下合并kotlin数据类?

Is there a way to merge kotlin data classes without specifying all the properties?

data class MyDataClass(val prop1: String, val prop2: Int, ...//many props)

具有以下签名的功能:

fun merge(left: MyDataClass, right: MyDataClass): MyDataClass

此函数检查两个类上的每个属性,而在其中不同的地方,使用left参数创建一个新的MyDataClass.

where this function checks each property on both classes and where they are different uses the left parameter to create a new MyDataClass.

使用kotlin-reflect或其他方法是否有可能?

Is this possible possible using kotlin-reflect, or some other means?

更清晰

这是对我想做的事的更好描述

Here is a better description of what i want to be able to do

  data class Bob(
        val name: String?,
        val age: Int?,
        val remoteId: String?,
        val id: String)

@Test
fun bob(){

    val original = Bob(id = "local_id", name = null, age = null, remoteId = null)
    val withName = original.copy(name = "Ben")
    val withAge = original.copy(age = 1)
    val withRemoteId = original.copy(remoteId = "remote_id")

    //TODO: merge without accessing all properties
    // val result = 
    assertThat(result).isEqualTo(Bob(id = "local_id", name = "Ben", age=1, remoteId = "remote_id"))
}

推荐答案

infix fun <T : Any> T.merge(mapping: KProperty1<T, *>.() -> Any?): T {
    //data class always has primary constructor ---v
    val constructor = this::class.primaryConstructor!!
    //calculate the property order
    val order = constructor.parameters.mapIndexed { index, it -> it.name to index }
                                      .associate { it };

    // merge properties
    @Suppress("UNCHECKED_CAST")
    val merged = (this::class as KClass<T>).declaredMemberProperties
                                           .sortedWith(compareBy{ order[it.name]})
                                           .map { it.mapping() }
                                           .toTypedArray()


    return constructor.call(*merged);
}

编辑

infix fun <T : Any> T.merge(right: T): T {
    val left = this;
    return left merge mapping@ {
        //    v--- implement your own merge strategy
        return@mapping this.get(left) ?: this.get(right);
    };
}

示例

val original = Bob(id = "local_id", name = null, age = null, remoteId = null)
val withName = original.copy(name = "Ben")
val withAge = original.copy(age = 1)
val withRemoteId = original.copy(remoteId = "remote_id")

val result = withName merge withAge merge withRemoteId;

这篇关于在Kotlin中合并/合并数据类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆