如何在Scala应用程序的设计中实现不变性?

时间:2011-11-03 19:49:13

标签: scala

作为scala和当前java开发人员的新手,scala旨在鼓励在课堂设计中使用不变性。

这实际上如何转化为类的设计?我想到的唯一一件事就是案例类。是否强烈鼓励案例类定义数据?例?在Scala设计类中,如何鼓励不变性?

作为一名java开发人员,定义数据的类是可变的。应该将等效的Scala类定义为案例类?

1 个答案:

答案 0 :(得分:11)

嗯,案例类肯定有帮助,但最大的贡献者可能是集合库。默认集合是不可变的,并且这些方法适用于通过生成新集合而不是变异来操纵集合。由于不可变集合是持久性的,因此不需要复制整个集合,这是Java中经常需要做的事情。

除此之外,for-comprehension是monadic理解,它有助于执行不可变任务,有尾递归优化,这在不可变算法中非常重要,并且在许多库中一般关注不变性,例如解析器组合器和xml。

最后,请注意,您必须要求var获得一些可变性。参数是不可变的,valvar一样短。与Java相比,参数是可变的,您需要添加 final关键字以获得不变性。而在Scala中,保持不变是容易或容易的,而在Java中,保持可变性更容易。

<强>附录

Persistent data structures在其修改版本之间共享部分的数据结构。这可能有点难以理解,所以让我们考虑Scala的List,这是非常基本且易于理解的。

Scala List由两个类组成,称为 cons Nil。前者实际上是在Scala中编写的::,但我会用传统的名称来引用它。

Nil是空列表。它不包含任何东西。依赖于列表不为空的方法(例如headtail会抛出异常,而其他方法可以正常工作。

当然, cons 必须代表非空列表。事实上, cons 恰好有两个元素:一个值和一个列表。这些元素称为 head tail

因此,包含三个元素的列表由三个缺点组成,因为每个缺点只包含一个值,加上Nil。它必须有Nil,因为缺点必须指向列表。由于列表不是循环的,因此其中一个缺点必须指向缺点以外的其他内容。

此类列表的一个例子是:

val list = 1 :: 2 :: 3 :: Nil

现在,Scala List的组件是不可变的。不能改变缺点的值和列表。不可变性的一个好处是,从不需要在传递之前或从其他方法接收之后复制集合:您知道该列表不能更改。

现在,让我们考虑如果修改该列表会发生什么。让我们考虑两个修改:删除第一个元素并添加一个新元素。

我们可以使用方法tail删除一个元素,其名称根本不是巧合。所以,我们写道:

val list2 = list.tail

list2将指向list tail 所指向的相同列表。什么都没有创建:我们只是重用list的一部分。所以,让我们将一个元素添加到list2然后:

val list3 = 0 :: list2

我们在那里创建了一个新的缺点。这个新缺点的值( head )等于0,其 tail 指向list2。请注意,listlist3都指向相同的list2。这些元素由listlist3 共享

还有许多其他持久性数据结构。您正在操作的数据是不可变的这一事实使得共享组件变得容易。

人们可以在Chris Okasaki的书中找到关于这个主题的更多信息,Purely Functional Data Structures,或者他可以免费获得thesis同名的信息。