2013-12-16 72 views
4

我有一個Scala案例類,它具有某些val的參數。我有幾個使用這個案例類的方法。假設我的案例類定義如下:具有行爲的Scala中的案例類

case class CaseA(a: Int, b: List[CaseB]) 
case class CaseB(a: Int, b: text, c: Boolean) 

CaseA和CaseB都代表我的案例類的域模型。但是當我在應用程序中使用它們時,我想根據CaseB的布爾字段向CaseA添加一些行爲。例如,讓我們假設在CaseA中,val b有4個CaseB對象。我想添加一個可以通過b運行的行爲,並告訴我CaseB中的任何一個元素的val c是否設置爲true。

我沒有想出什麼是以下實現CaseA的:

case class CaseA(a: Int, b: List[CaseB], c: Boolean) 

但是這種方法的問題是,當我從數據庫加載我CaseA對象,我不需要有VAL因爲val c是計算出來的,而不是CaseA對象的一部分。我更進一步,將我的CaseA修改爲如下所示:

case class CaseA(a: Int, b: List[CaseB], c: Option[Boolean]) 

我可以看到它已經變得很難看了。我怎樣才能將行爲添加到我的案例類中,以便valc不需要成爲CaseA對象的一部分,並且每次運行時都要計算它?

回答

5

我會用的情況下,一個懶惰的價值,你不需要下的所有元素

case class CaseB(a:Int,b:String,c:Boolean) 
case class CaseA(a:Int,b:List[CaseB]){ 
    lazy val c = b exists (_.c) 
} 

val ca = CaseA(42, List( 
    CaseB(1,"hello",false), 
    CaseB(2,",",false), 
    CaseB(3,"world",true)) 
    ) 

println(ca.c) 

要回答你的一些評論的問題如果你想使用mixin的特質,你可以這樣做以下:

case class CaseB(a:Int,b:String,c:Boolean) 
case class CaseA(a:Int,b:List[CaseB]) 
trait CanCheck extends CaseA{ 
    lazy val c = b exists (_.c) 
} 

val ca = new CaseA(42, List( 
    CaseB(1,"hello",false), 
    CaseB(2,",",false), 
    CaseB(3,"world",true)) 
    ) with CanCheck 

println(ca.c) 

請注意,您需要使用new關鍵字,使這項工作

+0

如果需要重新計算「lazy val」和「def」,只需交換即可。用戶代碼將保持完全相同,雖然:) – Felix

1

我不明白你在做什麼與數據庫。忽略這一點,我會做到以下幾點:

case class CaseA(a: Int, b: List[CaseB]){ 
    val c = b.exists(_.c) 
} 
+0

如何分離行爲b.exisis(_ .c)離開我的案例類? – sparkr

+0

你可以用一個函數輕鬆做到這一點:def oneIsTrue(ca:CaseA)= ca.b.exists(_。c),但是,你應該考慮這個功能的實際屬性。 – Felix

+0

我在思考更多關於使用具有行爲的特徵,我可以稍後在我的課程中混合使用它! – sparkr

3

在兩個方面:

1)定義C作爲VAL,甚至更好,爲DEF:

case class CaseA(a: Int, b: List[CaseB]){ 
    val c = b.exists(_.c) 
} 

2)使用隱式包裝:

case class CaseA(a: Int, b: List[CaseB]) 
implicit class CaseAC(underlying: CaseA) { 
    val c = underlying.b.exists(_.c) 
} 
val x = CaseA(3, Nil) 
// x: CaseA = CaseA(3,List()) 

x.c 
// Boolean = false 

如果您不需要存儲c,你可以使用隱式值類別,它們甚至更薄包裝