如何在 Scala 中实现功能完备的不可变 类?

How to make fully functional immutable classes in Scala?

我注意到 Scala 有大小写 类。这些似乎是用于模式匹配的,但我喜欢我可以用它们来做到这一点:

val bankAccount1 = new BankAccount("Daniel", 100)
val bankAccount2 = bankAccount1.copy(funds = 200)

现在 "Daniel" 有两个银行账户,一个有 100 美元,一个有 200 美元。但是当事情变得更复杂时,BankAccount 需要被子类化,这不起作用,因为 case 类 不能扩展其他 case 类。

我想要不可变的 类 比可以扩展成更不可变的 类。就像我希望能够扩展 BankAccount 以具有不可变的子 类 SavingsBankAccountCheckingBankAccount。我不确定此时我是否需要 extend/implement Clonable 接口或定义自定义复制方法或类似的东西。我不想在 类.

中放置太多样板文件

(如果可能的话),我如何在 Scala 中制作不可变的 类,它可以被复制和子类化,并且不会过于混乱或冗长?

我认为在 Scala 中执行此操作的惯用方法是使用封装而不是继承。例如你可以有:

case class BankAccount(id: AccountId, customer: Customer)
case class SavingsBankAccount(account: BankAccount, line: SavingsLine)

这样您将保持不变性和自动应用、取消应用、equals、hashCode 和复制方法生成的良好特性。

但是,如果您真的想使用继承,您别无选择,只能推出您自己的自定义解决方案。例如实现一个特性SubclassableCaseClass,它实现了帮助方法以快速定义方法案例类免费给你。

想想你的 BankAccount 是否真的需要具体。

我可以拥有一个不是储蓄或支票类型的银行账户吗?

如果这个问题的答案是否定的(在这个例子中我猜是),你可以使用摘要 class 或...

特质 !

http://www.scala-lang.org/old/node/126

当你真的不需要层次结构时,你可以用特征做很多事情。实际上 traits 比抽象的 classes 更好,因为你可以具有可组合性。

我发现在 scala 中编程大多数时候不需要扩展具体对象,特别是 class 只是打包数据的对象。

如果您确实需要 BankAccount 来具体说明,我猜您只剩下您已经建议的内容了。 :(