Kotlin中是否有一个didSet / willSet类似物?

我喜欢这个Swift语法; 这对许多事情非常有帮助:

var foo: Bar = Bar() { willSet { baz.prepareToDoTheThing() } didSet { baz.doTheThing() } } 

我很想在Kotlin做这个。 但是, 我找不到合适的语法 !

Kotlin有这样的东西吗?

 var foo: Bar = Bar() willSet() { baz.prepareToDoTheThing() } didSet() { baz.doTheThing() } 

尽管Kotlin没有提供内置的Swift风格的解决方案,但是您仍然可以通过几种方法来实现,这取决于您的目标是什么。

  • 有可observable(...)委托(在stdlib中)允许您处理属性更改。 用法示例:

     var foo: String by Delegates.observable("bar") { property, old, new -> println("$property has changed from $old to $new") } 

    在这里, "bar"是属性foo的初始值,lambda在属性被赋值后每次被调用,允许你观察变化。还有可vetoable(...)委托 ,可以让你阻止变更。

  • 您可以使用自定义设置器来执行实际值更改之前/之后的任意代码:

     var foo: String = "foo" set(value: String) { baz.prepareToDoTheThing() field = value baz.doTheThing() } 

    正如@KirillRakhman指出的那样,这个解决方案非常有效,因为它不会在方法调用和对象中引入任何开销,但是在多个属性的情况下代码将会被重复一些。

  • 通常,您可以实现自己的属性委托 ,在getValue(...)setValue(...)函数中显式提供属性行为。

    为了简化您的任务,使用ObservableProperty<T>抽象类,允许您实现观察属性更改的vetoable (如上面的observablevetoable )。示例:

     var foo: String by object : ObservableProperty<String>("bar") { override fun beforeChange(property: KProperty<*>, oldValue: String, newValue: String): Boolean { baz.prepareToDoTheThing() return true // return false if you don't want the change } override fun afterChange(property: KProperty<*>, oldValue: String, newValue: String) { baz.doTheThing() } } 

    为了您的方便,您可以编写一个创建委托对象的函数:

     fun <T> observing(initialValue: T, willSet: () -> Unit = { }, didSet: () -> Unit = { } ) = object : ObservableProperty<T>(initialValue) { override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true.apply { willSet() } override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = didSet() } 

    然后,您只需将lambda传递给它,因为willSetdidSet (它们的默认参数是{ } )。 用法:

     var foo: String by observing("bar", willSet = { baz.prepareToDoTheThing() }, didSet = { baz.doTheThing() }) var baq: String by observing("bar", didSet = { println(baq) }) 

在任何情况下,您都应该确保观察更改的代码不会再次设置属性,因为它可能属于无限递归,否则您可以在观察代码中检查是否递归调用setter。