我一直在学习Kotlin,并遇到了开放属性的概念。来自C ++的“开放”概念很有意义,并且将该逻辑扩展到属性也是如此。但是,我无法想到open val
/ var
实际上是必要或有用的任何情况。我知道它们何时对接口有意义,但对具体的类却没有意义。此外,覆盖getter / setter很有道理,但没有用新的支持字段重新定义属性。例如,假设您具有这种类结构:
open class Foo {
open var str = "Hello"
}
class Bar : Foo() {
override var str = "world"
init {
println(str)
println(super.str) // Shows that Bar actually contains "hello" and "world"
}
}
在我看来,使Foo将str
作为构造函数参数似乎是一种更好的设计,例如:
open class Foo(var str = "Hello") // Maybe make a secondary constructor
class Bar : Foo("world") // Bar has only 1 string
这不仅更简洁,而且似乎通常是更好的设计。这也是它倾向于在C ++中完成的方式,所以也许我只是看不到其他方式的好处。我只能看到用新的值覆盖val
/ var
的唯一可能是,由于某种原因,它是否需要使用super
的值,例如
override val foo = super.foo * 2
似乎仍然是人为的。
您何时发现此功能有用?是否可以提高效率或易于使用?
答案 0 :(得分:2)
open
字段使您可以重新定义getter和setter方法。如果只返回常量,这几乎是没有意义的。但是,更改getter / setter行为具有(无限的)潜力,因此,我将提出一些想法:
// propagate get/set to parent class
class Bar : Foo() {
override var str
get() = super.str.toUpperCase()
set(value) {
super.str = value
}
}
// creates a backing field for this property
class Bar : Foo() {
override var str = "World"
get() = field.toLowerCase()
// no need to define custom set if we don't need it in this case
// set(value) { field = value }
}
// instead of writing custom get/set, you can also use delegates
class Bar : Foo() {
override var str by Delegates.observable("world"){ prop, old, new ->
println("${prop.name} changed from $old to $new")
}
}