Home > Enterprise >  Specify field to copy in data classes - Kotlin
Specify field to copy in data classes - Kotlin

Time:12-28

Is there a way to specify the field to be copied in copy by, say, passing the variable name as a parameter in a function? Here is an example to illustrate what I mean. Supposed we have below:

val myData = User()

data class User(
    val firstName: String = "",
    val lastName: String = "",
    val email: String = ""
)

What I would like to do is create a function that does the following:

fun update(fieldToBeUpdated: String, value: String) {
    myData.update {
        it.copy(fieldToBeUpdated = value)
    }
}

Of course, this doesn't work, because the compiler says

cannot find a parameter with this name: fieldToBeUpdated

Does anybody know how to achieve this, or is this not possible in Kotlin?

CodePudding user response:

It is possible but it is not pretty. First thing is to make sure to add kotlin-reflect dependency to your pom.xml:

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-reflect</artifactId>
    <version>your-kotlin-version</version>
</dependency>

And then you will need some reflection features to make this possible. Something along the following lines should do the trick:

import kotlin.reflect.full.instanceParameter
import kotlin.reflect.full.memberFunctions

fun main(args: Array<String>) {
    val myData = User()

    println(myData)
    println(myData.update("firstName", "Test"))
}

fun User.update(fieldToBeUpdated: String, value: String): User {
    val copy = this::class.memberFunctions.first { it.name == "copy" }
    val instanceParameter = copy.instanceParameter!!
    val parameterToBeUpdated = copy.parameters.first { it.name == fieldToBeUpdated }
    return copy.callBy(mapOf(instanceParameter to this, parameterToBeUpdated to value)) as User
}

data class User(val firstName: String = "",
                val lastName: String = "",
                val email: String = "")
  • Related