对于scala中的对象是不可变的,需要什么?

时间:2012-12-17 16:00:14

标签: scala

答案是这样的:

对象的实例化使用' val'而不是' var'。

正在创建的对象的每个成员变量也是' val'而不是' var'。这是为了防止用户在设置后更新对象值。

2 个答案:

答案 0 :(得分:7)

如果该对象的用户无法改变对象,则该对象是不可变的。这意味着它必须没有公共方法来重新分配任何成员变量或改变这些变量引用的任何对象。如果所有对象的成员都是val,那么这确保了前者(即它们不能被重新分配),而不是后者(即如果这些变量引用的对象本身是可变的,它们仍然可以被突变即使它们仅被val s)引用,也会对它们调用变异方法。

另请注意,即使成员被声明为var s,如果对象的方法实际上没有重新分配变量(或者对它们调用变异方法),对象仍然可以是不可变的 - 当然,假设它们是'私有。

因此只有val个成员对于一个不可变的对象既不必要也不充分。该对象是由val还是var(或两者)引用,在这方面没有任何区别。

答案 1 :(得分:1)

@ sepp2k很好地正确地解释了技术上不可变的对象的标准。他的回答中遗漏的一个微妙点是,并非所有成员变量都对应于外部可见的状态。成员也可以是例如一个缓存的内部值,用于存储一些本地的,难以计算的数据,这些数据不能从外部直接看到(因此在Scala中被限定为private[this])。对象可以具有这样的var成员,例如存储计算的哈希值。它甚至可以通过公共getter访问 - 只要访问者的行为纯粹是功能性的,即它总是为同一对象上的每次调用产生相同的值(除了它在重用内部缓存值时返回更快)。

Scala编译器知道这种区别,因此它可以帮助人们正确地实现不可变类,即使在内部使用可变状态也是如此。当泛型类型变化发挥作用时,这很重要。也就是说,编译器允许泛型类型参数是协变的,即使该类包含此类型的可重新分配的字段 - 只要这些字段是private[this],确保一个人不能引用具有静态的包含对象比定义对象的类型更弱的类型(这可能是导致类型错误的方差的前提条件)。

使用代码示例在Programming in Scala的第19.7节中更详细地解释了这一点。