作为scala和当前java开发人员的新手,scala旨在鼓励在课堂设计中使用不变性。
这实际上如何转化为类的设计?我想到的唯一一件事就是案例类。是否强烈鼓励案例类定义数据?例?在Scala设计类中,如何鼓励不变性?
作为一名java开发人员,定义数据的类是可变的。应该将等效的Scala类定义为案例类?
答案 0 :(得分:11)
嗯,案例类肯定有帮助,但最大的贡献者可能是集合库。默认集合是不可变的,并且这些方法适用于通过生成新集合而不是变异来操纵集合。由于不可变集合是持久性的,因此不需要复制整个集合,这是Java中经常需要做的事情。
除此之外,for-comprehension是monadic理解,它有助于执行不可变任务,有尾递归优化,这在不可变算法中非常重要,并且在许多库中一般关注不变性,例如解析器组合器和xml。
最后,请注意,您必须要求var
获得一些可变性。参数是不可变的,val
与var
一样短。与Java相比,参数是可变的,您需要添加 final
关键字以获得不变性。而在Scala中,保持不变是容易或容易的,而在Java中,保持可变性更容易。
<强>附录强>
Persistent data structures是在其修改版本之间共享部分的数据结构。这可能有点难以理解,所以让我们考虑Scala的List
,这是非常基本且易于理解的。
Scala List
由两个类组成,称为 cons 和Nil
。前者实际上是在Scala中编写的::
,但我会用传统的名称来引用它。
Nil
是空列表。它不包含任何东西。依赖于列表不为空的方法(例如head
和tail
会抛出异常,而其他方法可以正常工作。
当然, 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
。请注意,list
和list3
都指向相同的list2
。这些元素由list
和list3
共享。
还有许多其他持久性数据结构。您正在操作的数据是不可变的这一事实使得共享组件变得容易。
人们可以在Chris Okasaki的书中找到关于这个主题的更多信息,Purely Functional Data Structures,或者他可以免费获得thesis同名的信息。