Есть ли более СУХОЙ способ использования наблюдаемого свойства делегата Kotlin? - PullRequest
0 голосов
/ 08 ноября 2018

Я использую наблюдаемый шаблон для отслеживания изменений в объекте. Для этого я использовал сборку observable от Kotlin. У меня все работает нормально, но для отслеживания некоторых изменений мне приходится повторять один и тот же код для каждого атрибута. Это мой код:

class Employee(
     id: String,
     name: String,
     surname: String,
     age: Int,
     salary: Int) {


     val changes = HashMap<String, Pair<Any, Any>>()


     val id = id //Id is immutable

var name: String by Delegates.observable(name) { prop, old, new ->
    if (old != new) {
        changes.put(prop.name, Pair(old, new))
        println("${prop.name} has changed from $old to $new")
    }
}

var surname: String by Delegates.observable(surname) { prop, old, new ->
    if (old != new) {
        changes.put(prop.name, Pair(old, new))
        println("${prop.name} has changed from $old to $new")
    }
}

var age: Int by Delegates.observable(age) { prop, old, new ->
    if (old != new) {
        changes.put(prop.name, Pair(old, new))
        println("${prop.name} has changed from $old to $new")
    }
}

var salary: Int by Delegates.observable(salary) { prop, old, new ->
    if (old != new) {
        changes.put(prop.name, Pair(old, new))
        println("${prop.name} has changed from $old to $new")
    }
 }

}

Как видите, я повторяю эти строки кода для каждого атрибута:

by Delegates.observable(name) { prop, old, new ->
if (old != new) {
    changes.put(prop.name, Pair(old, new))
    println("${prop.name} has changed from $old to $new")
    }
 }

У кого-нибудь есть идея сделать этот код более СУХИМЫМ, чтобы мне не приходилось копировать и вставлять строки везде, я посмотрел онлайн, но не смог найти способ определить логику в другом месте и применить ее ко всем атрибуты в классе.

1 Ответ

0 голосов
/ 08 ноября 2018

Вам не нужно явно повторно объявлять такой метод. Вы можете легко передавать ссылки на методы в Kotlin. Таким образом, вы можете сделать это:

val age = Delegates.observable(age, ::handler) // Notice `::handler`
// repeat for the others...

// And this is the actual function:
fun handler(prop: KProperty<*>, old: Any, new: Any){
    if (old != new) {
        changes.put(prop.name, old to new)
        println("${prop.name} has changed from $old to $new")
    }
}

::handler передает ссылку на метод, который обрабатывает их все. Вам все равно придется повторить инициализацию, но вам не нужно создавать один и тот же метод-обработчик несколько раз.

Также, если id - это значение, и вы ничего с ним не делаете, вы можете просто сделать это:

class Employee(
     val id: String, // Adding `val` or `var` in the constructor makes it an actual variable, instead of just local to the constructor. ***NOTE:*** This only applies to primary constructors. 
     name: String,
     surname: String,
     age: Int,
     salary: Int) {
...