我想检测我的类属性的任何更改值,然后我可以在那之后再做一次操作。换句话说,如果属性的某个特定数据发生了变化,那么特定事件将在此时触发。实际上,如果它是其他编程语言(如Java)中的普通类,那么我认为在数据修改或在C#中使用委托后我可以使用setter来完成这项工作。但由于Kotlin很新,我根本找不到任何解决方案。 我试图超载财产,但任何机会都没有成功。我也想使用接口,但是因为它是数据类,所以我不知道应该怎么做。
以下是示例课程。在这种情况下,如何检测Age或名称何时更改?
data class Person(var Name: String, var Age: Int)
所以,如果有人对此有任何想法,请帮助。
注意:在我的情况下,必须使用数据类。
答案 0 :(得分:13)
数据类确实没有为此做。由于它们的属性必须在主构造函数中声明,因此您无法真正为它们添加自定义行为。
也就是说,如果必须,您可以通过复制属性,然后使用自定义设置器或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")
}
}
这样你仍然有一个构造函数,它将name和age作为参数,但是它们被分配给类体内的属性。对于数据类,这是不可能的,因为数据类的每个构造函数参数也必须是属性(标记为val
或var
)。有关详情,请参阅有关constructors,properties和data 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.'")
}
}