Skip to content
rktoomey edited this page May 19, 2011 · 9 revisions

Traits and abstract superclasses

With one easy extra step, Salat can handle fields and collections typed to a trait or an abstract superclass.

Under the hood

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.

Compare and contrast

Without traits

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)

With traits

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))

With abstract superclasses

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)

Collection support

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])
Clone this wiki locally