¿Cómo detectar valores modificados en la class de datos Kotlin?

Quiero detectar cualquier valor cambiado de una propiedad de mi class para poder hacer otra operación después de eso. En otras palabras, si se cambia uno de los datos específicos de una propiedad, entonces se activará un evento específico para entonces. En realidad, si es una class normal en otros lenguajes de progtwigción como Java, entonces creo que podría usar setter para hacer este trabajo después de que los datos hayan sido modificados o use delegate en C #. Pero como Kotlin es muy nuevo, no pude encontrar ninguna solución. Intenté sobrecargar properties pero no tuve éxito por casualidad. Quería utilizar la interfaz para esto también, pero de nuevo, ya que es la class de datos, no tengo idea de cómo se debe hacer.

Debajo está la class de muestra. En tal situación, ¿cómo detectar cuándo se cambia la edad o el nombre?

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

Entonces, si alguien tiene alguna idea al respecto, por favor ayuda.

Nota: en mi situación, se debe usar la class de datos.

Las classs de datos realmente no están hechas para esto. Como sus properties deben declararse en el constructor primario, no se puede agregar un comportamiento personalizado.

Dicho esto, si es necesario, puede lograrlo duplicando las properties y, a continuación, utilizando los adaptadores personalizados o Delegates.observable .

Esta es una forma de hacerlo con los configuradores personalizados, aquí tendrá acceso a las properties de name y age públicamente visibles, que también mantienen actualizadas las declaradas en el constructor:

 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 declanetworking in the primary ctor } var age = _age set(value) { println("Age changed from $age to $value") field = value _age = value } } 

La misma idea, con Delegates.observable , que hace parte del trabajo para usted, aquí su única sobrecarga es establecer las properties declaradas en el constructor a los nuevos valores:

 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 } } 

El uso de cualquiera de estos se ve así (el toString se verá un poco feo con los guiones bajos):

 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 

Edite para responder la pregunta a continuación:

Si no necesita que su class sea una class de datos, la siguiente sería probablemente la solución más simple:

 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") } } 

De esta forma, todavía tienes un constructor que toma el nombre y la edad como parameters, pero se los asigna a las properties que están dentro del cuerpo de la class. Esto no es posible con una class de datos, ya que cada parámetro de constructor de una class de datos tiene que ser también una propiedad (marcado val o var ). Para get más información, puede ver la documentation sobre constructores , properties y classs de datos .

Propiedades delegadas

Hay ciertos types comunes de properties, que, aunque podemos implementarlas manualmente cada vez que las necesitamos, sería muy bueno implementarlas de una vez por todas y ponerlas en una biblioteca. Ejemplos incluyen

properties diferidas: el valor se calcula solo en el primer acceso, properties observables: los oyentes reciben notifications sobre los cambios en esta propiedad, el almacenamiento de properties en un map, en lugar de un campo separado para cada propiedad. Para cubrir estos (y otros) casos, Kotlin admite properties delegadas:

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

La syntax es: val / var: by. La expresión después de es el delegado, porque get () (y set ()) correspondiente a la propiedad se delegará a sus methods getValue () y setValue (). Los delegates de propiedad no tienen que implementar ninguna interfaz, pero tienen que proporcionar una function getValue () (y setValue () – para var's). Por ejemplo:

 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.'") } } 
  • Descartar el cuadro de dialog en la tecla Atrás presionada
  • ¿Cómo funciona el ejemplo de los numbers primos de la documentation de Corotines de Kotlin?
  • "Si" vs. "tomar si" en Kotlin?
  • ¿Cómo se simula emitir 2 streams infinitas observables y tener otras observables que las fusionan y amortiguan cada 10 segundos?
  • No existe la relación Heroku postgres "information_schema.session_state"
  • Spring Data JPA Cómo utilizar Kotlin nulls en lugar de Opcional
  • Kotlin: ¿Cómo get y configurar un text para TextView en Android usando Kotlin?
  • Inyectar no funciona con el segundo constructor
  • Dependencias faltantes o conflictivas para Anko floatingActionButton
  • testing JOOQ postgres jsonb column for key exists
  • Retrofit se bloquea cuando lanzo una exception en un interceptor