How to distribute behavior by class classes in scala

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 that define different objects, such as

 case class Person ( _id: Option[BSONObjectID], name: String, version: Option[BSONLong] ) extends Entity 

I need a way to set _id and version later from a generic method that works with Entity, because I have to share this behavior with all Entities and not try to write it hundreds of times ;-). I would like to be able

 def createID(entity: Entity): Entity = { entity.copy(_id = ..., version = ...) } 

... but, of course, this will not compile, since the object does not have a copy method. It is generated for each individual class of the class by the compiler ...

What is the best way to achieve this in scala?

So that someone does not ask: I should use case classes, because this is what the third-party library extracts for me from the requests I receive, and instances of the case class are what are later serialized to BSON / MongoDB ...

+4
source share
2 answers

Indeed, you can find a way to implement something like this in

Create a common trait for all case classes that support the copy method (id = newId)

but since it’s quite difficult for my use case, I would rather just 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 collaborative behavior on these fields. Of course, you should modify the definition of your base class accordingly:

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

To make it clear: this only works if the behavior you want to use for multiple classes only affects (in my case the changes) one attribute ...

+2
source

Will the trait work?

 trait MongoIdHandler { def createId(entity : Entity) : Option[BSONObjectID] = { ..} def setVersion(version : String) : Unit = { ..} } case class Person (..) with MongoIdHandler .. 

If any of the instances requires specialized versions of the id generator, they can override the "default" impl provided by the tag.

0
source

All Articles