为什么Kotlin隐式地调用属性的getter和setter?

为什么Kotlin隐式地调用属性的getter和setter?,kotlin,Kotlin,当您试图访问属性时,Kotlin隐式调用属性的getter/setter函数的目的是什么?如果你想使用getter和setter,你可以很容易地调用它们,这难道不是getter和setter的目的吗?Kotlin的版本基本上只引入了“字段”标识符的额外复杂性,并引入了如下奇怪之处,其中对象的行为可能与其预期的接口不同: interface Counter { var count: Int fun increment() { count = count + 1

当您试图访问属性时,Kotlin隐式调用属性的getter/setter函数的目的是什么?如果你想使用getter和setter,你可以很容易地调用它们,这难道不是getter和setter的目的吗?Kotlin的版本基本上只引入了“字段”标识符的额外复杂性,并引入了如下奇怪之处,其中对象的行为可能与其预期的接口不同:

interface Counter {
    var count: Int
    fun increment() {
        count = count + 1
    }
}

class WeirdCounter: Counter {
    override var count: Int = 0
        get() = field
        set(value) {println("ignore the value")}
}

只是想了解这背后的意图。

Kotlin使用getter和setter实现属性的方式基本上是许多其他语言的常见做法和最佳做法

与Java一样,“裸”字段简单、清晰且易于使用;但是裸字段有问题:

  • 它们公开了一个实现细节(字段,尤其是它的类型),防止将来更改它

  • 它们不允许类控制自己的状态

当然,这些对于简单的值类来说不是问题,但是对于更复杂的类来说,它们可能是一个真正的问题

例如,您可能希望更改类存储其状态的方式(例如,将
long
替换为
BigDecimal
),但如果该类是流行库的公共界面的一部分,那么成千上万的用户将非常恼火

或者假设您可以确保字符串属性始终以小写形式存储,而不带前导或尾随空格,这将非常方便。但是对于“bare”属性,无法强制执行这一点

所以通常的模式是有一个私有的字段,只能从类本身(由您控制)中访问并提供访问器方法

这使您可以完全控制。您可以更改内部表示形式,只要您根据需要更新访问器方法以转换为新表单或从新表单转换为新表单。您的setter可以执行任何规范化、格式化或其他操作,以对状态实施任何限制

然而,在Java这样的语言中,这比一个简单的字段更笨拙和冗长:访问器方法将一行字段变为七行(不包括空行,也不包括文档注释,所以这可能更像是将三行变为21行)。而调用getter方法只需多几个字符(使用
get
()
)而不是引用字段,调用setter比简单赋值直观得多

结果是,要么开发人员做了正确的事情,并用样板文件填充他们的类(包括对可维护性和错误风险的所有影响),要么他们不麻烦,也不冒上述问题的风险

Kotlin提供了两全其美的功能:一个简单的属性在定义和访问它时看起来就像一个字段。因此,您可以得到精简、简洁、清晰的代码。但是它是通过一个私有的支持字段(如果需要)和访问器方法实现的s、 因此,您也可以获得这些方法的所有优点。如果您需要添加验证、更改表示或记录所有访问或其他任何内容,您可以选择使用自己的实现替换默认访问器

您的
WeirdCounter
示例很奇怪,但并不像您想象的那么可怕(或像您想象的那样)。在面向对象语言中,类是自己状态的主人,而其他类通常不知道也不应该知道其内部(这样,它们就与那些内部的更改隔离开来)如果一个类需要在setter中做一些违反直觉的事情,那么这只是一个问题,如果它破坏了类的契约——但是这将是一个bug,并且应该在测试中变得明显,如果不是在其他地方的话


在实践中,类控制对其状态的访问的能力比类使用该状态执行愚蠢或恶意操作的风险更重要(这很容易发现).

Kotlin使用getter和setter实现属性的方式基本上是许多其他语言中的常见做法和最佳做法

与Java中一样,“裸”字段简单、清晰且易于使用;但裸字段存在问题

  • 它们公开了一个实现细节(字段,尤其是它的类型),防止将来更改它

  • 它们不允许类控制自己的状态

当然,这些对于简单的值类来说不是问题,但是对于更复杂的类来说,它们可能是一个真正的问题

例如,您可能希望更改类存储其状态的方式(例如,将
long
替换为
BigDecimal
),但如果该类是流行库的公共界面的一部分,那么成千上万的用户将非常恼火

或者假设您可以确保字符串属性始终以小写形式存储,而不带前导或尾随空格,这将非常方便。但是对于“bare”属性,无法强制执行这一点

因此通常的模式是有一个私有的字段,只能从类本身(由您控制)中访问;并提供访问器方法

这使您可以完全控制。您可以更改内部表示形式,只要您根据需要更新访问器方法以转换为新表单或从新表单转换为新表单。您的setter可以执行任何规范化、格式化或其他操作,以对状态实施任何限制

然而,在Java这样的语言中,这比一个简单的字段更笨拙和冗长:访问器方法将一行字段转换为七行(不包括空行,也不包括文档注释,所以这可能更像是将三行转换为21行)。而调用getter方法只需要几行