如何检测Data class Kotlin中更改的值?

时间:2017-06-10 05:04:16

标签: android kotlin

我想检测我的类属性的任何更改值,然后我可以在那之后再做一次操作。换句话说,如果属性的某个特定数据发生了变化,那么特定事件将在此时触发。实际上,如果它是其他编程语言(如Java)中的普通类,那么我认为在数据修改或在C#中使用委托后我可以使用setter来完成这项工作。但由于Kotlin很新,我根本找不到任何解决方案。 我试图超载财产,但任何机会都没有成功。我也想使用接口,但是因为它是数据类,所以我不知道应该怎么做。

以下是示例课程。在这种情况下,如何检测Age或名称何时更改?

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

所以,如果有人对此有任何想法,请帮助。

注意:在我的情况下,必须使用数据类。

2 个答案:

答案 0 :(得分:13)

数据类确实没有为此做。由于它们的属性必须在主构造函数中声明,因此您无法真正为它们添加自定义行为。

也就是说,如果必须,您可以通过复制属性,然后使用自定义设置器或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
        }

}

同样的想法,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")
    }

}

这样你仍然有一个构造函数,它将name和age作为参数,但是它们被分配给类体内的属性。对于数据类,这是不可能的,因为数据类的每个构造函数参数也必须是属性(标记为valvar)。有关详情,请参阅有关constructorspropertiesdata classes的文档。

答案 1 :(得分:1)

  

委托属性

     

有一些常见的属性,尽管我们可以   每次我们需要它们时手动实现它们,会非常好   一劳永逸地实施,并放入图书馆。例子包括

     

延迟属性:仅在首次访问时才计算值,   可观察属性:侦听器会收到有关此更改的通知   属性,在地图中存储属性,而不是单独的字段   每个属性。为了涵盖这些(和其他)案例,Kotlin支持   委托属性:

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

语法为:val / var:by。表达方式   之后是by委托,因为get()(和set())对应   该属性将被委托给其getValue()和setValue()   方法。属性委托不必实现任何接口,但是   他们必须提供getValue()函数(和setValue() - for   VAR' S)。例如:

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