【问题标题】:Kotlin automatically generates Getters and Setters, but WHY?Kotlin 会自动生成 Getter 和 Setter,但为什么?
【发布时间】:2022-10-17 21:54:16
【问题描述】:

我是学习 Kotlin 的新手,刚刚介绍了每个对象属性的 Getter 和 Setter 都是在幕后自动生成的,就像 Lombok 直接内置在语言中一样(就我而言很棒!),但是现在我剩下的问题是为什么它甚至会打扰?

我知道您可以覆盖默认值以更改它们的行为方式,但是为什么当您需要做一些更复杂的事情而不是仅仅获取或设置值时创建它们的情况不只是这种情况,而是只是正常访问属性?

以前使用过很多 Java,我了解支持和反对使用 Getter 和 Setter 的争论。许多人说它们实际上是毫无意义的,并且是一种糟糕的 OOP 方法,其他人会说它们是最佳实践,应该在任何地方使用。许多现代框架和库的编写方式使得它们在很多情况下都是必要的。这个论点跨越了许多不同的语言,但是这个问题并不是关于它们在 OOP 中作为一个整体的理论原因,我正在寻找具体的洞察力,了解为什么默认情况下在 Kotlin 中使用它们,什么时候我(也许是天真的) 眼睛看起来不需要。

会是什么实际的如果 Kotlin 没有生成标准的 Getter 和 Setter 并且点表示法只是直接访问该属性,会有什么区别?在语法上,据我所见,它产生相同的结果,只是增加了一些步骤。

【问题讨论】:

    标签: kotlin oop getter setter accessor


    【解决方案1】:

    如果 Kotlin 不生成标准的 Getters 和 Setters 并且点表示法只是直接访问该属性,那么实际的区别是什么?

    所以你的建议是,对于没有自定义 getter/setter 的属性,

    // Accessing x would access the field backing the property directly
    // no getter or setter
    var x: Int = 1
    

    对于具有自定义 getter/setter 的属性,

    // both a field and a setter is generated for y
    var y: Int = 1
        set(newValue) { 
            field = newValue.also { println("y is being set!") } 
        }
    
    // only a getter is generated for z, no field
    val z get() = 1
    

    将根据您编写的内容生成适当的 getter 或 setter 或两者。

    好吧,这在某些方面会存在问题。这是我能想到的。

    首先,所有这些“何时(不)生成getter / setter”逻辑将使编译器更加复杂。当您可以无条件地为每个属性简单地生成一个 getter 和 setter 时,为什么要这样做?

    其次,对于与 Kotlin 代码交互的 Java 代码,它们只有一个可以使用的字段,在 x 的情况下,Java 中的公共字段看起来一点也不惯用......让我们说在某个时候你向x 添加一个getter,以便它是从其他东西计算出来的,而不是由一个字段支持,那么所有Java 代码都会中断,因为不再有一个字段。我不确定在 Kotlin/JS 上是否也是如此。

    第三,通过反射访问属性值会更烦人。您需要检查它是否有吸气剂。如果是,请调用它。否则,请改为访问支持字段。他们可以在KProperty 上为您提供一个辅助属性,为您完成此任务,但是,这比简单地调用getter 并完成它要复杂得多。

    请注意,仅对于 JVM,就 JVM 而言,您可以使用注释 @JvmField 使属性没有 getter 和 setter。尽管如此,Kotlin 的反射 API 仍然会找到 getter 和 setter。

    【讨论】:

      【解决方案2】:

      反对 getter 和 setter 的两个主要论点:

      1. 冗长。但它们在 Kotlin 中并不冗长。

      2. 性能开销。但这与现代 JVM 无关。

        使用类的原始设计中的 getter 和 setter 会更安全,即使它们只是通过对字段的读取和写入。如果您以后需要,它留下了添加副作用的可能性。强制使用属性可以防止您将自己设计成一个角落。

        此外,当完成相同任务的方法较少时,一种语言更容易读写。您永远不必记住要在类*问的属性是使用 getter 函数语法还是使用标准属性语法。

      【讨论】:

      • 我看到的反对 getter 和 setter 的主要论点是它们是数据结构的特性,而不是对象,因此它们导致过程编程,而不是 OOP。
      • @jaco0646 是的,那是另一个。这一点在 Kotlin 中也不适用,因为当您没有专门定义自定义实现时,getter 和 setter 是底层且微不足道的。