mardi 17 juillet 2018

Kotlin - Overwrite Obj Props With Modified Obj Props if Not Null

TL;DR:

How do I make this less redundant?

if (personModification.firstName != null) {person.firstName = personModification.firstName}
if (personModification.lastName != null) {person.lastName = personModification.lastName}
if (personModification.job != null) {person.job = personModification.job}


The long version: I have a simple problem. I have a class Person:

class Person (val firstName: String?, 
              val lastName: String?, 
              val job: String?)

and I have a class called PersonModification:

class PersonModification(val firstName: String?, 
                         val lastName: String?, 
                         val job: String?)

The task is to overwrite any Person property values with PersonModification values, IF the PersonModification property isn't null. If you care, the business logic behind this is an API endpoint which modifies Person and takes a PersonModification as an argument (but can change all, or any, of the properties, so we don't want to overwrite valid old values with nulls). The solution to this looks like this.

if (personModification.firstName != null) {person.firstName = personModification.firstName}
if (personModification.lastName != null) {person.lastName = personModification.lastName}
if (personModification.job != null) {person.job = personModification.job}

I was told this is redundant (and I agree). The solution pseudocode looks like this:

foreach(propName in personProps){
  if (personModification["propName"] != null) {person["propName"] = personModification["propName"]}
}

Of course, this isn't JavaScript, so it's not that easy. My reflection solution is below, but imo, it's better to have redundancy than do reflection here. What are my other options to remove the redundancy?


Refelection:

package kotlin.reflect;

class Person (val firstName: String?, 
              val lastName: String?, 
              val job: String?)

class PersonModification(val firstName: String?, 
                         val lastName: String?, 
                         val job: String?)

// Reflection - a bad solution. Impossible without it.
//https://stackoverflow.com/questions/35525122/kotlin-data-class-how-to-read-the-value-of-property-if-i-dont-know-its-name-at
inline fun <reified T : Any> Any.getThroughReflection(propertyName: String): T? {
    val getterName = "get" + propertyName.capitalize()
    return try {
        javaClass.getMethod(getterName).invoke(this) as? T
    } catch (e: NoSuchMethodException) {
        null
    }
}

fun main(args: Array<String>) {

var person: Person = Person("Bob","Dylan","Artist")
val personModification: PersonModification = PersonModification("Jane","Smith","Placeholder")
val personClassPropertyNames = listOf("firstName", "lastName", "job")

for(properyName in personClassPropertyNames) {
    println(properyName)
    val currentValue = person.getThroughReflection<String>(properyName)
    val modifiedValue = personModification.getThroughReflection<String>(properyName)
    println(currentValue)
    if(modifiedValue != null){
        val property = outputs::class.memberProperties.find { it.name == "firstName" }
        if (property is KMutableProperty<*>) {
            property.setter.call(person, "123")
        }
    }
}

println("test")

}

You can copy and paste here to run it: https://try.kotlinlang.org/





Aucun commentaire:

Enregistrer un commentaire