Функция общего сеттера Kotlin - PullRequest
0 голосов
/ 30 августа 2018

Я новичок в котлине. Интересно, возможно ли это

Я хочу создать функцию, которая будет изменять значение свойств объекта и возвращать сам объект. Основным преимуществом является то, что я могу связать этот сеттер.

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)

но я получаю ошибку "неизвестные ссылки"

Этот вопрос помечен как дубликат, однако возможный дубликат вопроса специально хочет изменить свойство «имя», но я хочу изменить любой объект, который передается от функции к объекту. Не могу связать точку между двумя вопросами. @ Мойра Пожалуйста, дайте ответ, который объясняет это. большое спасибо

Ответы [ 3 ]

0 голосов
/ 30 августа 2018

У вас есть ошибка, потому что когда вы делаете this[propName] = value, вы пытаетесь использовать this в качестве списка, но это не список, это Person, и он не перегружает оператор [].

Что вы можете сделать, это добавить проверку установленного свойства:

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

   fun setter(propName:String, value:Any): Person{
      return this.apply {
          if (propName == "name" && value is String?) {
              it.name = value as String?
          } else if (propName == "age" && value is Int?) {
              it.age = value as Int?
          } else {
              // handle unknown property or value has incorrect type
          }
      }
   }
}

Еще одно более динамичное решение без отражения:

class Person {
   private var fields: Map<String, Any?> = HashMap()

   fun setter(propName:String, value:Any): Person{
      return this.apply {
          it.fields[propName] = value;
      }
   }

   fun getName() = fields["name"]
}

Если вы также хотите избавиться от геттеров, вам нужно использовать отражение.

0 голосов
/ 30 августа 2018

Почему бы просто не упростить ваш ответ на

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 не требуется, его единственным эффектом является прекращение поддержки нетривиальных свойств.

Кроме того, если вы называете это operator fun set вместо fun setter,

this[propName] = value
Синтаксис

может использоваться для его вызова.

0 голосов
/ 30 августа 2018

После поиска в поисках, я думаю, что могу дать ответ, но чисто полагаясь на java вместо kotlin. Будет здорово, если кто-нибудь сможет дать лучший ответ на 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;
  }
}

использование как это

 person
    .setter(propName = "age", value = 30.00)
    .setter(propName = "asdf", value = "asdf")
    .setter(propName = "name", value = "A Vidy")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...