简体   繁体   English

kotlin 中显式 getter 的目的是什么?

[英]What is the purpose of explicit getters in kotlin?

Using getters and setters is a very well known practice in object oriented languages.在面向 object 的语言中,使用 getter 和 setter 是一种众所周知的做法。 This is done in order to have a greater control on the variables.这样做是为了更好地控制变量。 To achieve this, we make the variables private in java and hence we need both getters and setters there.为了实现这一点,我们在 java 中将变量设为私有,因此我们需要 getter 和 setter。

But in kotlin this is not the case.但在 kotlin 中并非如此。 Here even public variables are accessed through getters and setters by default.默认情况下,这里甚至通过 getter 和 setter 访问公共变量。 Though setters can be used to validate an assignment to a variable, getters just return the variable as it is stored (and I think this is it for them).虽然 setter 可用于验证对变量的赋值,但 getter 只是返回存储的变量(我认为这就是为他们准备的)。 Hence custom getters are not required at all.因此,根本不需要自定义 getter。

I have also seen some wrong usage of this feature where instead of writing a zero argument function, they use a val and do the computation in the getter.我还看到了此功能的一些错误用法,他们没有编写零参数 function,而是使用 val 并在 getter 中进行计算。 This creates an illusion that the thing is just a val but in reality it does not store anything and instead it performs a computation every time.这会产生一种错觉,认为该事物只是一个 val,但实际上它不存储任何内容,而是每次都执行计算。

So is there a real need to have a custom getter?那么是否真的需要自定义吸气剂?

getters just return the variable as it is stored (and I think this is it for them). getter 只是返回存储的变量(我认为这就是为他们准备的)。 Hence custom getters are not required at all.因此,根本不需要自定义 getter。

If that was really the case, why have getters at all in Java?如果真是这样,为什么在 Java 中有吸气剂? One of the goals of encapsulation is to make sure a change in the class doesn't change it's API.封装的目标之一是确保 class 的变化不会改变它的 API。 It's the same in Kotlin.在 Kotlin 中也是如此。

I have also seen some wrong usage of this feature where instead of writing a zero argument function, they use a val and do the computation in the getter.我还看到了此功能的一些错误用法,他们没有编写零参数 function,而是使用 val 并在 getter 中进行计算。 This creates an illusion that the thing is just a val but in reality it does not store anything and instead it performs a computation every time.这会产生一种错觉,认为该事物只是一个 val,但实际上它不存储任何内容,而是每次都执行计算。

This is a perfectly valid use case for a custom getter.对于自定义 getter,这是一个完全有效的用例。 In Kotlin, one must not assume that using a property is entirely free of overhead.在 Kotlin 中,不能假设使用属性完全没有开销。 There are many questions to ask yourself when choosing between a property with a getter or a zero-arg function:在使用 getter 或零参数 function 的属性之间进行选择时,有很多问题要问自己:

  • Does it describe behavior?它描述行为吗? Use a function ( walk() , build() , etc)使用 function ( walk()build()等)
  • Does it describe state?它是否描述了 state? Use a property ( firstName , lastIndex , etc)使用属性( firstNamelastIndex等)

Additionally, a property getter should not throw an exception, should be either cheap to calculate or cached on first access, and should return the same result for multiple consecutive executions.此外,属性 getter 不应该抛出异常,应该在第一次访问时计算成本低或缓存,并且应该为多次连续执行返回相同的结果。 Here's examples from the standard library:以下是标准库中的示例:

  • ArrayDeque.first() is a function, it throws if deque is empty. ArrayDeque.first()是一个 function,如果双端队列为空则抛出。
  • List.lastIndex is a property, it's cheap to calculate. List.lastIndex是一个属性,计算起来很便宜。
  • Lazy<T>.value is a property, the value is computed and cached on first access. Lazy<T>.value是一个属性,该值在首次访问时计算并缓存。

Most delegated properties make use of custom getters.大多数委托属性都使用自定义 getter。

More reading:更多阅读:

Just some more info.只是更多的信息。 Other than readability, the possibility of defining a custom getter allows you to evolve a class without changing its public members, even if you started with a simple val with no custom getter.除了可读性之外,定义自定义 getter 的可能性允许您在不更改其公共成员的情况下演变 class,即使您从没有自定义 getter 的简单val开始。

In a language without properties like Java, if you define a public field:在没有 Java 等属性的语言中,如果您定义公共字段:

public class Foo {
    public final int value;

    public Foo(int value) {
        this.value = value;
    }
}

And then later you want to modify the class to add a feature where it returns negated values if you flip a Boolean, there's no way to do it without breaking code that uses the original version of the class.然后稍后您想要修改 class 以添加一个功能,如果您翻转 Boolean,它将返回否定值,如果不破坏使用 ZA2F2ED4F8EBC2CBB4C21A29DC4 原始版本的代码,就无法做到这一点。 So you should have used getters and setters to begin with.因此,您应该从一开始就使用 getter 和 setter。

But in Kotlin, you can't directly expose a backing field like this, so it's impossible to paint yourself in a corner like you could with a public field in Java.但是在 Kotlin 中,你不能像这样直接暴露背景字段,所以不可能像在 Java 中使用公共字段那样在角落里画自己。 If your original class is like this:如果你原来的 class 是这样的:

class Foo(val value: Int)

You could modify it like this to add the feature and have no impact on code that already uses the class.您可以像这样修改它以添加该功能,并且对已经使用 class 的代码没有影响。

class Foo(private val originalValue: Int) {
    var isNegated = false

    val value: Int
        get() = if (isNegated) -originalValue else originalValue
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM