¿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.'") } } 
  • ¿Es posible simular accesos de Mockito en Kotlin?
  • ¿Por qué Smart Cast falla por el valor anulable después de establecer el valor y verificar si es nulo?
  • ¿Cómo se verifica el tipo genérico en Kotlin?
  • Cómo hacer un bucle multicondicional para kotlin
  • ¿De qué se trata este package "KotlinRulezzz"?
  • Kotlin HTML-Builder
  • kotlin llamando a una function de mutación en la delegación de la class
  • El complemento kapt de Kotlin para gradle no funciona para el set fuente personalizado (JMH)
  • La synchronization de Gradle falló: Causa: com / android / build / gradle / BaseExtension
  • ¿Los types de datos de Kotlin están basados ​​en types de datos Java primitivos o no primitivos?
  • iniciar AsyncTask por segunda vez