Kotlin中开放属性的用途是什么?

时间:2019-07-25 21:36:34

标签: kotlin

我一直在学习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

似乎仍然是人为的。

您何时发现此功能有用?是否可以提高效率或易于使用?

1 个答案:

答案 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")
    }
}