Как определить значения, измененные в классе данных Kotlin?

Я хочу обнаружить любые значения, измененные в свойстве моего класса, чтобы после этого я мог выполнить другую операцию. Другими словами, если одна из конкретных данных свойства изменяется, то к этому времени будет срабатывать определенное событие. На самом деле, если это обычный класс на других языках программирования, таких как Java, то я думаю, что я мог бы использовать setter для выполнения этого задания после того, как данные изменили или использовали делегат в C #. Но так как Котлин очень новый, я вообще не нашел никакого решения. Я попытался перегрузить собственность, но не был успешным ни в коем случае. Я тоже хотел использовать интерфейс для этого, но опять же, поскольку это класс данных, я понятия не имел, как это сделать.

Ниже приведен пример класса. В такой ситуации, как определить, когда изменяется возраст или имя?

data class Person(var Name: String, var Age: Int) 

Поэтому, пожалуйста, если у кого-нибудь есть идеи об этом, пожалуйста, помогите.

Примечание. В моей ситуации должен использоваться класс данных.

Классы данных на самом деле не созданы для этого. Поскольку их свойства должны быть объявлены в основном конструкторе, вы не можете добавить к ним настраиваемое поведение.

При этом, если нужно, вы можете добиться этого, дублируя свойства, а затем либо используя пользовательские сеттеры, либо Delegates.observable .

Вот как это сделать с настраиваемыми настройщиками, здесь вы будете получать доступ к общедоступным свойствам name и age , которые также сохраняют те, которые были объявлены в конструкторе:

 data class Person(private var _name: String, private var _age: Int) { var name = _name set(value) { println("Name changed from $name to $value") field = value // sets the backing field for `name` _name = value // sets the `_name` property declared in the primary ctor } var age = _age set(value) { println("Age changed from $age to $value") field = value _age = value } } 

Такая же идея, с Delegates.observable , которая выполняет некоторую работу для вас, здесь ваши единственные накладные расходы – это определение свойств, объявленных в конструкторе, новыми значениями:

 data class Person(private var _name: String, private var _age: Int) { var name: String by Delegates.observable(_name) { prop, old, new -> println("Name changed from $old to $new") _name = new } var age: Int by Delegates.observable(_age) { prop, old, new -> println("Age changed from $old to $new") _age = new } } 

Использование любого из них выглядит следующим образом ( toString будет выглядеть немного уродливым с символами подчеркивания):

 val sally = Person("Sally", 50) println(sally) // Person(_name=Sally, _age=50) sally.age = 51 // Age changed from 50 to 51 println(sally) // Person(_name=Sally, _age=51) println(sally.name) // Sally println(sally.age) // 51 

Измените ответ на вопрос ниже:

Если вам не нужен ваш класс для класса данных, вероятно, самым простым решением будет следующее:

 class Person(name: String, age: Int) { var name: String by Delegates.observable(name) { _, old, new -> println("Name changed from $old to $new") } var age: Int by Delegates.observable(age) { _, old, new -> println("Age changed from $old to $new") } } 

Таким образом, у вас все еще есть конструктор, который берет имя и возраст в качестве параметров, но они присваиваются свойствам, находящимся внутри тела класса. Это невозможно с классом данных, потому что каждый параметр конструктора класса данных должен также быть свойством (с пометкой val или var ). Кроме того, вы можете увидеть документацию о конструкторах , свойствах и классах данных .

Делегированные свойства

Существуют определенные общие виды свойств, которые, хотя мы можем реализовать их вручную каждый раз, когда мы в них нуждаемся, было бы очень приятно реализовать раз и навсегда и поместить в библиотеку. Примеры включают

ленивые свойства: значение вычисляется только при первом доступе, наблюдаемые свойства: слушатели получают уведомление об изменениях этого свойства, сохраняя свойства на карте, а не отдельное поле для каждого свойства. Чтобы покрыть эти (и другие) случаи, Kotlin поддерживает делегированные свойства:

 class Example { var p: String by Delegate() } 

Синтаксис: val / var: by. Выражение after by является делегатом, потому что get () (и set ()), соответствующее свойству, будет делегирован его методам getValue () и setValue (). Делегатам свойств не нужно реализовывать какой-либо интерфейс, но они должны предоставлять функцию getValue () (и setValue () – для var). Например:

 class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value has been assigned to '${property.name} in $thisRef.'") } }