基本上,性狀可以擴展爲any class,所以最好將它們用於常規類(OOP風格)。
反正你平等的合同仍然是斷開的,無論你的絕招(注意,標準Java的equals
定義上Any
,所使用的默認情況下,讓我們在HashMap
甚至==
說):
scala> trait MyTrait extends MyCaseClass {
| override def equals(m: Any): Boolean = false
| }
defined trait MyTrait
scala> val myCT = new MyCaseClass("hi") with MyTrait
myCT: MyCaseClass with MyTrait = MyCaseClass(hi)
scala> val myC = new MyCaseClass("hi")
myC: MyCaseClass = MyCaseClass(hi)
scala> myC.equals(myCT)
res4: Boolean = true
scala> myCT.equals(myC)
res5: Boolean = false
此外, Hashcode/equals
是不是唯一的原因...
與其他類擴展case class
是不自然的,因爲case class
代表ADT所以它僅機型數據 - 不行爲。
這就是爲什麼你不應該添加任何方法(在OOD條款case class
es是專爲貧血的方法)。因此,排除方法後 - 一個特點,只能用類混合變成廢話的使用特點與case類的點是模擬析取(這樣特質的接口在這裏 - 不混合插件):
//your data model (Haskell-like):
data Color = Red | Blue
//Scala
trait Color
case object Red extends Color
case object Blue extends Color
如果Color
只能用Blue
混合 - 這是一樣
data Color = Blue
即使你需要更復雜的數據,像
//your data model (Haskell-like):
data Color = BlueLike | RedLike
data BlueLike = Blue | LightBlue
data RedLike = Red | Pink
//Scala
trait Color extends Red
trait BlueLike extends Color
trait RedLike extends Color
case class Red(name: String) extends RedLike //is OK
case class Blue(name: String) extends BlueLike //won't compile!!
結合Color
只有Red
似乎不是一個好方法(一般),因爲你將無法case object Blue extends BlueLike
P.S.案例類不打算用於OOP風格(混入是OOP的一部分) - 它們與類型類/模式匹配更好地交互。所以我建議將你的複雜類似方法的邏輯從case class中移走。一種方法可以是:
trait MyCaseClassLogic1 {
def applyLogic(cc: MyCaseClass, param: String) = {}
}
trait MyCaseClassLogic2 extends MyCaseClassLogic {
def applyLogic2(cc: MyCaseClass, param: String) = {}
}
object MyCaseClassLogic extends MyCaseClassLogic1 with MyCaseClassLogic2
你可以使用自助型或trait extends
在這裏,但你可以很容易地發現,這是多餘的,因爲applyLogic
勢必MyCaseClass
只:)
另一種方法是implicit class
(或者你可以嘗試更類似類型的先進的東西)
implicit class MyCaseClassLogic(o: MyCaseClass) {
def applyLogic = {}
}
PS2貧血與豐富。因爲它適用於不可變(無狀態)數據,所以它不是精確的貧血模型。如果您閱讀the article,Martin Fowler的方法是OOP/OOD,默認情況下是有狀態的 - 這就是他在文章的大部分部分中所暗示的,暗示服務層和業務層應該具有不同的狀態。在FP中(至少在我的實踐中),我們仍然將領域邏輯與服務邏輯分開,但是我們也將操作與數據分開(在每一層中),這是另一回事。
在我看來,案例類有專門的意義。它們意味着你可以用一個簡潔和無鍋爐的方式爲你的域對象建模。他們提供散列碼,平等,適用和不適用,這些都有助於我們輕鬆地對這些對象進行模式匹配。有一個'特質'繼承一個case類會感到奇怪和不自然。話雖如此,這個問題通常感覺像[XY問題](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。你想達到什麼目的? –
http://stackoverflow.com/questions/12854941/why-can-a-scala-trait-extend-a-class – dk14
@YuvalItzchakov:我有一個包含數據的類。根據(複雜的)規則,它們是不同種類的,由哪些特徵混合而成。根據這些特徵,預計會出現不同的行爲。因此,我的特徵得到了行爲,並擴展了主數據對象,使它們變得豐富。 (我知道有一個關於[豐富vs貧血模型]的討論(http://stackoverflow.com/q/23314330/4533188),但[我贊成豐富的方法](http://www.martinfowler.com /bliki/AnemicDomainModel.html)。)問題是我可以讓我的數據對象成爲一個案例類,還是把它作爲一個普通的類。 – Make42