How to share behavior over case classes in scala

case-class, inheritance, scala

Solution

Indeed one can find a way to implement something like this at

Create common trait for all case classes supporting copy(id=newId) method

but since it is quite complicated for my use case I would prefer just to create two new classes

class MongoId(var id : BSONObjectID = null) {
    def generate = {
        id = BSONObjectID.generate
    }
}

class MongoVersion(var version: Long = 0) {
    def update = {
        version = System.currentTimeMillis
    }
}

and implemented the shared behavior regarding these fields there. Of course you have to change the definition of your base class accordingly:

abstract class Entity {
    def _id: MongoId
    def version: MongoVersion
}

To make it clear: This works only if the behavior you want to share over several case classes does only affect (in my case changes) one attribute ...

Problem

Implementing my domain model in scala using case classes I got ``` abstract class Entity { val _id: Option[BSONObjectID] val version: Option[BSONLong] } ``` and several case classes defining the different entities like ``` case class Person ( _id: Option[BSONObjectID], name: String, version: Option[BSONLong] ) extends Entity ``` What I need is a way to set the _id and version later on from a generic method which operates on an Entity because I have to share this behavior over all Entities and want to avoid writing it down hundreds of times ;-). I would love to be able to ``` def createID(entity: Entity): Entity = { entity.copy(_id = ..., version = ...) } ``` ...but of course this does not compile since an Entity has no copy-method. It is generated for each single case class by the compiler... What is the best way to achieve this in scala? To prevent somebody asking: I have to use case classes since this is what the third-party-library is extracting for me from the requests I get and the case class instances are what is serialized back to BSON / MongoDB later on...

Original source