Kotlin 覆盖成员集并获取

Kotlin override member set and get

有没有人知道更好的方法来监听自己基地内的成员变化class?

class FOO {
    val t: String
}

class BOO: FOO {
    fun x(val t: String) {
        // notify when t was changed 
    }
}

在我看来,带有 Observer 的 JavaRx 就足够了。 Kotlin Delegate 不适用于继承(或者我还找不到方法)。我想出的最好办法是在 "BOO" 中覆盖 "t" 的 setter 和 getter。但这有点尴尬,因为 "Why should i overwrite a member?" 或 "Why do i have to define set and get when i just need set?"

到目前为止我的解决方案是:

import kotlin.properties.Delegates

fun main(args: Array<String>) {
    var foo = FOO()
    foo.t = "foo"
    foo.printT()

    var boo = BOO()
    boo.t = "boo"
    boo.printT()
}

open class FOO () {
    open var t: String? = "origin"
    set(value) {
        println("\t origin setter is called")
        field = String() + value // create a copy (original it is not a String :D)
    }
    get() {
        println("\t origin getter is called")
        return field
    }

    fun printT() = println(t)
}


class BOO (): FOO () {
    override var t: String?
    set(value) {
        // thats all what i need
        println("\t overwritten setter is called")
        super.t = value // execute origin setter
    }
    get() {
        println("\t overwritten getter is called")
        return super.t
    }
}
open class FOO {
    var t: String = "origin"
        set(value) {
            field = value
            x(t)
        }

    open fun x(t: String) {
        println("FOO: t=$t")
    }
}

open class BOO : FOO() {
    override fun x(t: String) {
        super.x(t)
        println("BOO: t=$t")
    }
}

更新:

我个人认为它看起来有点奇怪,但如果您不需要重写任何成员(字段或方法),那么您可以将 onChange 方法设为 属性:

open class FOO(val onChange: (t: String) -> Unit = FOO.defaultOnChange) {
    companion object {
        val defaultOnChange: (t: String) -> Unit = { println("FOO: t=$it") }
    }

    var t: String = "origin"
        set(value) {
            field = value
            onChange(t)
        }
}

open class BOO : FOO({ defaultOnChange(it); println("BOO: t=$it") })

类似的方法,但 Delegates.observable(), 参见 Language reference:

import kotlin.properties.Delegates

open class UserBase {
    var name: String by Delegates.observable("<no name>") { prop, old, new ->
        println("$old -> $new")
        onChange(new)
    }

    // could be abstract, if class is abstract
    open fun onChange(v: String?) {}
}

class User : UserBase() {
    override fun onChange(v: String?) {
        println("I was changed in my base class: ${v}")
    }
}

fun main(args: Array<String>) {
    val user = User()
    user.name = "first"
    user.name = "second"
}

为什么不直接覆盖?喜欢这里:

open class FOO () {
    open var t: String = "origin"

    fun printT() = println(t)
}

class BOO (): FOO () {
    override var t: String
    get() = super.t
    set(value) {
        // thats all you need
        println("\t overwritten setter is called")
        super.t = value 
    }
}

我在这里看到的唯一缺点是需要显式覆盖 getter,但这只是一个额外的行。