Kotlin переопределить набор элементов и получить
Кто-нибудь знает лучший способ прослушивания изменений членов внутри собственного базового класса?
class FOO {
val t: String
}
class BOO: FOO {
fun x(val t: String) {
// notify when t was changed
}
}
На мой взгляд Яваркс с наблюдателем был бы ко многому. Делегат Kotlin не работает с наследованием (или я еще не нашел способ). Лучшее, что я придумал, - это переопределить сеттер и геттер "т" в "БУ". Но это немного неудобно из-за этого "почему я должен перезаписывать член?"или "Почему я должен определить set и получить, когда мне просто нужно 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
}
}
3 ответа:
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()
, смотрите в справочник по языку: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 } }