2013-03-09 57 views
4

使用case類Scala中實現我的域模型我如何通過案例類共享行爲斯卡拉

abstract class Entity { 
    val _id: Option[BSONObjectID] 
    val version: Option[BSONLong] 
} 

和幾個case類定義諸如

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

不同的實體,我需要什麼一種方法來設置_id和版本後來從一個實體上運行的泛型方法,因爲我必須在所有實體上共享這種行爲,並希望避免將其寫下數百次;-)。我希望能夠

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

...但當然這不會編譯,因爲一個實體沒有複製方法。它是由編譯器生成的每個單獨的案例類...

什麼是在scala中實現這一點的最佳方法?

爲了防止有人問:我必須使用大小寫類,因爲這是第三方庫從我得到的請求中提取的內容,而case類實例是稍後序列化回BSON/MongoDB的內容。 ...

+0

[爲所有支持copy(id = newId)方法的案例類創建常見特徵的可能重複(http://stackoverflow.com/questions/15078102/create-common-trait-for-all- case-classes-supporting-copyid-newid-method) – 2013-03-09 20:14:13

+0

爲什麼不把_id和版本位分開?你將會有一個案例類'Entity [T](_ id:...,version:...,data:T)'。 'T'可能是另一個具有適當數據的案例類。 – 2013-03-09 22:37:05

+0

對不起,但正如我所提到的案例類實例(包括id和版本)是由第三方庫創建的,因此這裏不是一個選項。 – jens 2013-03-09 23:17:28

回答

2

事實上,人們可以找到一種方法來實現這樣的事情在

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

,但因爲它是我的使用情況相當複雜,我寧願只是創建兩個新的類

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

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

並實施了關於這些領域的共享行爲。當然,你必須相應地改變你的基類的定義:

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

要清楚:這隻有當你想分享了幾個case類不只會影響的行爲(在我的情況是不同的)一個屬性...

0

會執行一項特質工作嗎?

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

case class Person (..) with MongoIdHandler .. 

如果任何實例需要特定版本的id生成器,他們可以覆蓋特性提供的'default'impl。

+0

不,不幸的是,這並沒有幫助,因爲我必須更改Person的id值,因爲Person是稍後被序列化爲BSON/MongoDB的對象。我無法找到一種方法來從任何不知道實體的確切類型的方法(如本例中的Person)中改變字段的值... – jens 2013-03-09 19:23:31