-
Notifications
You must be signed in to change notification settings - Fork 0
Traits
With one easy extra step, Salat can handle fields and collections typed to a trait or an abstract superclass.
By hinting to Salat that this trait or abstract class will be used to type a field or collection containing polymorphic implementation, the grater can memoize that information. Salat thus avoids a serious runtime performance hit.
Consider the following arrangement. No traits are used, so no special annotations are necessary. Salat simply does its job without asking for any more help.
case class Zeta(x: String)
case class Iota(z: Zeta)
In this example, Iota
's z
field is parameterized to a
trait, namely trait Zeta
. To avoid performance degradation at
run time, you must annotate trait Zeta
with the @Salat
annotation, as shown below.
import com.novus.salat.annotations._
@Salat
trait Zeta {
val x: String
}
case class Eta(x: String) extends Zeta
case class Iota(z: Zeta)
When Grater[Iota]
serializes an instance of Iota
, the @Salat
annotation tells the grater
to expect polymorphism:
the _typeHint
for the Zeta
object specifies that it is an instance of com.novus.salat.test.model.Eta
, not
com.novus.salat.test.model.Zeta
.
To deserialize from DBObject
back to Iota
, the _typeHint
field is necessary! See type hinting for
more information.
scala> val i = Iota(z = Eta("eta"))
i: com.novus.salat.test.model.Iota = Iota(Eta(eta))
scala> val dbo = grater[Iota].asDBObject(i)
dbo: com.mongodb.casbah.Imports.DBObject = { "_typeHint" :
"com.novus.salat.test.model.Iota" , "z" :
{ "_typeHint" : "com.novus.salat.test.model.Eta" , "x" : "eta"}}
scala> val i_* = grater[Iota].asObject(dbo)
i_*: com.novus.salat.test.model.Iota = Iota(Eta(eta))
Similarly, let's imagine that Zeta
were an abstract superclass, not a trait - you need to annotate it with @Salat
for exactly the same reasons:
import com.novus.salat.annotations._
@Salat
abstract class Zeta(val x: String)
case class Eta(override val x: String) extends Zeta(x)
case class Iota(z: Zeta)
Salat also supports parameterizing collections with a trait or abstract superclass. Again, this requires using type hints.
@Salat
trait SomeCommonTrait
case class SomeSubclassExtendingSaidTrait(b: Int) extends SomeCommonTrait
case class AnotherSubclassExtendingSaidTrait(d: Double) extends SomeCommonTrait
case class SomeContainerClass(e: String, theListWhichNeedsToBeTested: List[SomeCommonTrait])
@Salat
sealed abstract class Vertebrate
case class Bird(name : String, canFly : Boolean = true) extends Vertebrate
case class Squirrel(name : String, canFly : Boolean = false) extends Vertebrate
case class VertebrateList(vList : List[Vertebrate])