Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin general setter function

Tags:

kotlin

I am new to kotlin. I wonder if this is possible

I wish to create a function that will change the value of the properties of the object and return the object itself. The main benefit is that I can chain this setter.

class Person {
   var name:String? = null
   var age:Int? = null

   fun setter(propName:String, value:Any): Person{
      return this.apply {
          try {
              // the line below caused error
              this[propName] = value
          } catch(e:Exception){
              println(e.printStackTrace()) 
          }
      }
   }
}


//usage
var person = Person(null,null)
person
   .setter(name, "Baby")
   .setter(age, 20)

But I get error "unknown references"

This question is marked as duplicate, however the possible duplicate question specifically want to change the property of "name", but I wish to change anyProperty that is pass from the function to object. Can't seem to connect the dot between two questions. @Moira Kindly provide answer that explain it. thankyou

like image 358
vdj4y Avatar asked Dec 28 '25 23:12

vdj4y


2 Answers

Why not just simplify your answer to

fun setter(propName: String, value: Any): Person {
    val property = this::class.memberProperties.find { it.name == propName }
    when (property) {
        is KMutableProperty<*> ->
            property.setter.call(this, value)
        null -> 
            // no such property
        else ->
            // immutable property
    }
}

Java reflection isn't needed, its only effect is to stop non-trivial properties from being supported.

Also, if you call it operator fun set instead of fun setter, the

this[propName] = value

syntax can be used to call it.

like image 149
Alexey Romanov Avatar answered Dec 30 '25 23:12

Alexey Romanov


After googling around, I think I can provide an answer, but relying on java instead of kotlin purely. It will be great if someone can provide a better answer in kotlin.

class Person(
    var name: String,
    val age: Int
){

  fun setter(propName: String, value: Any): Person{
    var isFieldExistAndNotFinal = false
    try{
        val field = this.javaClass.getDeclaredField(propName)
        val isFieldFinal = (field.getModifiers() and java.lang.reflect.Modifier.FINAL == java.lang.reflect.Modifier.FINAL)
        if(!isFieldFinal) {
            // not final
            isFieldExistAndNotFinal = true
        }
        // final variable cannot be changed
        else throw ( Exception("field '$propName' is constant, in ${this.toString()}"))
    } catch (e: Exception) {
        // object does not have property
        println("$e in ${this.toString()}")
    }

    if(isFieldExistAndNotFinal){
        val property = this::class.memberProperties.find { it.name == propName }
        if (property is KMutableProperty<*>) {
            property.setter.call(this, value)
        }
    }
    return this;
  }
}

usage like this

 person
    .setter(propName = "age", value = 30.00)
    .setter(propName = "asdf", value = "asdf")
    .setter(propName = "name", value = "A Vidy")
like image 36
vdj4y Avatar answered Dec 30 '25 22:12

vdj4y



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!