scala - May mix-in traits extend case classes from a technical perspective? -


i read repeatedly on case classes shall not extended because case class implements equality method default , leads issues of equality. however, if trait extends case class, problematic?

case class mycaseclass(string: string) trait mytrait extends mycaseclass val myct = new mycaseclass("hi") mytrait 

i guess boils down question, whether mytrait forced mixable instantiations of mycaseclass or whether mytrait inheriting class members (field values , methods) of mytrait , overwriting them. in first case okay inherit mycaseclass, in latter case not okay. 1 it?

to investigate, advanced experiment with

trait mytrait extends mycaseclass {   def equals(m: mycaseclass): boolean = false   def equals(m: mycaseclass mytrait): boolean = false } val myc = new mycaseclass("hi") myct.equals(myc) // res0: boolean = true 

letting me believe equals of mycaseclass used, not 1 of mytrait. suggest okay trait extend case class (while not okay class extend case class).

however, not sure whether experiment legit. shed light on matter?

basically, trait can extend any class, it's better use them regular classes (oop-style).

anyway, equals contract still broken regardless of trick (note standard java's equals defined on any, used default let's in hashmap or ==):

scala> trait mytrait extends mycaseclass {      |   override def equals(m: any): boolean = false      | } defined trait mytrait  scala> val myct = new mycaseclass("hi") mytrait myct: mycaseclass 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 

besides, hashcode/equals isn't reason...

extending case class class unnatural because case class represents adt models data - not behavior.

that's why should not add methods (in ood terms case classes designed anemic approach). so, after eliminating methods - trait can mixed class becomes nonsense point of using traits case classes model disjunction (so traits interfaces here - not mix-ins):

//your data model (haskell-like): data color = red | blue  //scala trait color case object red extends color case object blue extends color 

if color mixed blue - it's same

data color = blue 

even if require more complex data, like

//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!! 

binding color red doesn't seem approach (in general) won't able case object blue extends bluelike

p.s. case classes not intended used in oop-style (mix-ins part of oop) - interact better type-classes/pattern-matching. recommend move complex method-like logic away case class. 1 approach be:

trait mycaseclasslogic1 {   def applylogic(cc: mycaseclass, param: string) = {} }  trait mycaseclasslogic2 extends mycaseclasslogic {   def applylogic2(cc: mycaseclass, param: string) = {} }  object mycaseclasslogic extends mycaseclasslogic1 mycaseclasslogic2 

you use self-type or trait extends here can notice it's redundant applylogic bound mycaseclass :)

another approach implicit class (or can try more advanced stuff type-classes)

implicit class mycaseclasslogic(o: mycaseclass) {   def applylogic = {} } 

p.s.2 anemic vs rich. adt not precisely anemic model applies immutable (stateless) data. if read the article, martin fowler's approach oop/ood stateful default - that's assumes in of part of article implying service layer , business layer should have separate states. in fp (at least in practice) still separate domain logic service-logic, separate operations data (in every layer), matter.


Comments

Popular posts from this blog

python - How to insert QWidgets in the middle of a Layout? -

python - serve multiple gunicorn django instances under nginx ubuntu -

module - Prestashop displayPaymentReturn hook url -