众所周知,Scala会自动为任何公共字段生成getter和setter,并将实际字段变量设为私有。为什么它比公开场地更好?
答案 0 :(得分:14)
对于其中一个,这允许使用(几个)def(s)交换公共var / val并仍然保持二进制兼容性。其次,它允许覆盖派生类中的var / val。
答案 1 :(得分:10)
首先,保持字段公开允许客户端读取和写入字段。由于拥有不可变对象是有益的,我建议将字段设为只读(可以通过将其声明为“val”而不是“var”来在Scala中实现。)
现在回到你的实际问题。如果您需要的不仅仅是琐碎的版本,Scala允许您定义自己的setter和getter。这对于维护不变量非常有用。对于setter,您可能需要检查字段设置的值。如果您将该字段本身公开,则您没有机会这样做。
这对于声明为“val”的字段也很有用。假设您有一个Array [X]类型的字段来表示类的内部状态。客户端现在可以获得对此数组的引用并对其进行修改 - 再次,您无法确保维护不变量。但由于您可以定义自己的getter,因此可以返回实际数组的副本。
当您在Java中创建引用类型“final public”的字段时,同样的参数适用 - 客户端无法重置引用但仍然修改引用所指向的对象。
相关说明:通过Scala中的getter访问字段看起来像是直接访问字段。关于这一点的好处是它允许访问一个字段并调用一个没有参数的方法看起来像是一样的东西。因此,如果您决定不再在某个字段中存储值,而是在运行中进行计算,则客户端无需关心,因为它对他来说看起来是一样的 - 这被称为{{3 }}
答案 2 :(得分:8)
简而言之:统一访问原则。
您可以使用val从超类实现抽象方法。想象一下虚拟图形包中的以下定义:
abstract class circle {
def bounds: Rectangle
def centre: Point
def radius: Double
}
有两个可能的子类,一个是根据边界框定义圆,另一个是根据中心和半径定义的。由于UAP,实现的细节可以完全抽象出来,并且可以轻松更改。
还有第三种可能性:懒惰的vals。这些对于避免一次又一次地重新计算我们的圆圈的边界非常有用,但很难想象如果没有统一的访问原则,如何实现懒惰的val。