代码之家  ›  专栏  ›  技术社区  ›  Michael

在Scala中为对象字段自动生成getter/setter到底有什么意义?

  •  11
  • Michael  · 技术社区  · 14 年前

    如我们所知,Scala为任何公共字段自动生成getter和setter,并将实际字段变量设为private。为什么这比公开场合要好?

    3 回复  |  直到 14 年前
        1
  •  14
  •   Silvio Bierman    14 年前

    其中一个允许用(两个)def交换公共var/val,并且仍然保持二进制兼容性。其次,它允许重写派生类中的var/val。

        2
  •  10
  •   weberste    14 年前

    首先,保持字段公共允许客户机读写字段。由于拥有不可变对象是有益的,我建议将该字段设置为只读(在Scala中可以通过将其声明为“val”而不是“var”来实现)。

    现在回到你的实际问题上来。Scala允许您定义自己的setter和getter,如果您需要的不仅仅是简单的版本。这对于保持不变量很有用。对于setter,您可能需要检查字段设置的值。如果你公开这个领域,你就没有机会这样做。

    这对于声明为“val”的字段也很有用。假设有一个Array[X]类型的字段来表示类的内部状态。客户机现在可以获得对这个数组的引用并修改它——同样,您也没有机会确保保持不变。但是由于可以定义自己的getter,因此可以返回实际数组的副本。

    当您在Java中将引用类型的字段设为“final public”时,同样的参数也适用——客户机无法重置引用,但仍然修改引用指向的对象。

    注意:通过Scala中的getter访问字段看起来像是直接访问字段。这方面的好处是它允许访问一个字段和调用一个对象上没有参数的方法看起来是一样的。所以,如果你决定不再在一个字段中存储一个值,而是动态地计算它,客户就不必在意了,因为对他来说它看起来是一样的——这就是所谓的 Uniform Access Principle

        3
  •  8
  •   Kevin Wright    14 年前

    简而言之:统一访问原则。

    可以使用val从超类实现抽象方法。想象一下某个虚构的图形包中的以下定义:

    abstract class circle {
      def bounds: Rectangle
      def centre: Point
      def radius: Double
    }
    

    有两个可能的子类,一个是用边界框定义圆,另一个是用中心和半径定义圆。由于有了UAP,实现的细节可以完全抽象出来,而且很容易更改。

    还有第三种可能:懒惰。这对于避免一次又一次地重新计算循环的边界是非常有用的,但是很难想象如果没有统一的访问原则,可以实现多慢的vals。