Say I have two traits that I would like to mixin to a class. The traits each implement an abstract method that the class needs.
trait Writable {
def serialize(out: java.io.DataOutput)
}
trait T1 extends Writable
trait A extends T1 {
val aNum: Int
abstract override def serialize(out: java.io.DataOutput) = {
super.serialize(out)
println("A serialize")
out.writeInt(aNum)
}
def action = println("A action")
}
trait B extends T1 {
val bNum: Int
abstract override def serialize(out: java.io.DataOutput) = {
super.serialize(out)
println("B serialize")
out.writeInt(bNum)
}
def action = println("B action")
}
abstract class M[CT1 <: T1](val mNum: Int) extends Writable {
this: M[CT1] with T1 =>
def serialize(out: java.io.DataOutput) = {
println("M serialize")
out.writeInt(mNum)
}
def action
}
I can then construct a concrete M with either A or B and serialize:
scala> val m1 = new M[A](10) with A { val aNum = 20 }
m1: M[A] with A = $anon$1@67c1e630
scala> val m2 = new M[B](20) with B { val bNum = 30 }
m2: M[B] with B = $anon$1@c36f58e
scala> val out = new java.io.DataOutputStream(new java.io.ByteArrayOutputStream())
out: java.io.DataOutputStream = java.io.DataOutputStream@87afebf
scala> m1.serialize(out)
M serialize
A serialize
scala> m2.serialize(out)
M serialize
B serialize
Everything works as expected. But how do I deserialize the objects while respecting the type of trait that is mixed into M? I could output the trait's name in the serialize method and then have M's deserialize method dispatch on the name but what if I have classes other than M that A and B can be mixed into? Then, each class would have to duplicate the behavior of M's dispatching deserialize. The problem gets even worse if I have multiple traits that need to get mixed into an object to make it concrete and each has it's own custom serialization/deserialization to do. Anyone tackle an issue like this?