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 = "")