Michael Lafayette
Michael Lafayette

Reputation: 3072

How to make fully functional immutable classes in Scala?

I noticed that Scala has case classes. These appear to be for pattern matching, but I like that I can do this with them:

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

Now "Daniel" has two bank accounts, one with $100 and one with $200. But when things get more complicated, BankAccount needs to be sub-classed and this doesn't work because case classes can't extend other case classes.

I want immutable classes than can be extended into more immutable classes. Like I want to be able to extend BankAccount to have immutable sub-classes SavingsBankAccount and CheckingBankAccount. I'm not sure if at this point I need to extend/implement the Clonable interface or define custom copy methods or something like that. I don't want to have to put too much boilerplate in the classes.

(If possible), how do I make immutable classes in Scala that can be copied and sub-classed and that aren't overly messy or verbose?

Upvotes: 1

Views: 160

Answers (2)

Onilton Maciel
Onilton Maciel

Reputation: 3699

Think if your BankAccount really needs to be concrete.

Can I have a BankAccount that is not of the type Savings or Checking?

If the answer to this question is no (in this example I guess it is), you could use a abstract class or...

traits !

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

When you don't really need hierarchies, you can do a lot with traits. Actually traits are better than abstract classes since you can have composability.

I found out programming in scala that most of the time you don't need to extend concrete objects, specially classes that just pack data.

If you really need BankAccount to be concrete, that I guess you are left with what you already suggested. :(

Upvotes: 0

nivox
nivox

Reputation: 2130

I think that the idiomatic way of doing that in Scala would be using encapsulation instead of inheritance. For instance you could have:

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

This way you would keep the good properties of immutability and automatic apply, unapply, equals, hashCode and copy method generation.

However if you really wanted to use inheritance you have no other choice than to roll out your own custom solution. For instance implementing a trait SubclassableCaseClass which implements helper methods for a quick definition of the methods case classes give you for free.

Upvotes: 3

Related Questions