我想要检测我的类的属性的任何值的更改,这样我就可以在那之后执行另一个操作.换言之,如果属性特定数据之一发生更改,则届时将触发特定事件.实际上,如果它是另一种编程语言(如Java)中的普通类,那么我认为可以在数据修改后使用setter来完成这项工作,或者使用C#中的委托.但是由于Kotlin是非常新的,我根本找不到任何解决方案. 我曾试图使房产超载,但碰巧没有成功.我也想用接口来实现这一点,但是由于它是数据类,我不知道该怎么做.

Below is the sample class. In such situation, how to detect when Age or name is changed?

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

So please if anyone have any ideas about this, please help.

Note: in my situation, data class must be used.

推荐答案

数据类不是为此而设计的.由于它们的属性必须在主构造函数中声明,因此不能真正向它们添加自定义行为.

也就是说,如果必须,可以通过复制属性,然后使用自定义setter或Delegates.observable来实现这一点.

这里有一种使用自定义设置器的方法,在这里,您将访问公共可见的nameage属性,这些属性使构造函数中声明的属性保持最新:

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
        }

}

Same idea, with Delegates.observable, which does some of the work for you, here your only overhead is setting the properties declared in the constructor to the new values:

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
    }

}

Usage of either of these looks like this (the toString will look a bit ugly with the underscores):

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

Edit to answer the question below:

If you didn't need your class to be a data class, the following would probably be the simplest solution:

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

}

这样,您仍然有一个以名称和年龄为参数的构造函数,但它们被分配给类主体内的属性.对于数据类,这是不可能的,因为数据类的每个构造函数参数也必须是属性(标记为valvar).有关更多信息,请参阅关于constructorspropertiesdata classes的文档.

Kotlin相关问答推荐

Kotlin -通过反射获得KProperty 1和CallableReference的实例

用浮点数或十进制数给出错误答案的阶乘计算

Gradle Jooq配置自定义生成器

插入/更新/upsert时不发出房间流

如何让Gradle8+在编译Kotlin代码之前编译Groovy代码?然后把它们混合在一个项目中?

当我通过媒体通知更改音乐时不要更新我的 UI

在 Kotlin 协程中切换 IO 和 UI 的正确方法是什么?

使用 Discord4j 交叉发布 Discord 消息

使用 LazyListScope 嵌套可组合项

Android 导航组件 - 向上导航打开相同的片段

从列表中的每个对象中 Select 属性

Kotlin 语言是如何用 Kotlin 编写的?

requireNotNull vs sure !! 操作符

如何捕获传递给模拟函数的参数并返回它?

如何获取Kotlin中变量的名称?

如何为 Java 调用者声明返回类型为void的 Kotlin Lambda?

Kotlin - computed var 属性的用处?

Android:Exoplayer - ExtractorMediaSource 已弃用

在android java类中使用Kotlin扩展

Kotlin内联属性的用例是什么?