Digamos que tengo dos características que me gustaría mezclar en una clase. Los rasgos implementan cada uno un método abstracto que la clase necesita.Rasgos y serialización/deserialización
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
}
A continuación, puedo construir un hormigón M con A o B y serializar:
scala> val m1 = new M[A](10) with A { val aNum = 20 }
m1: M[A] with A = [email protected]
scala> val m2 = new M[B](20) with B { val bNum = 30 }
m2: M[B] with B = [email protected]
scala> val out = new java.io.DataOutputStream(new java.io.ByteArrayOutputStream())
out: java.io.DataOutputStream = [email protected]
scala> m1.serialize(out)
M serialize
A serialize
scala> m2.serialize(out)
M serialize
B serialize
Todo funciona como se esperaba. Pero, ¿cómo deserializo los objetos respetando el tipo de rasgo que se mezcla en M? Podría mostrar el nombre del rasgo en el método de serialización y luego tener el envío del método de deserialización de M en el nombre, pero ¿qué sucede si tengo otras clases además de M en las que se pueden mezclar A y B? Entonces, cada clase tendría que duplicar el comportamiento de la deserialización del despacho de M. El problema empeora si tengo varios rasgos que necesitan mezclarse en un objeto para hacerlo concreto y cada uno tiene su propia serialización/deserialización personalizada para hacer. ¿Alguien aborda un problema como este?
No es claro cómo estas bibliotecas eligen qué rasgo de mixin a la clase de deserialización. ¿Podría explicarme cómo el marco elige entre "con A" o "con B"? – AnthonyF
Así que el rasgo A y el rasgo B contienen diferentes implementaciones de un método abstracto en la clase M. He editado la pregunta para reflejar ese hecho. Estoy buscando componer un objeto con comportamiento definido en rasgos y permitir que ese objeto sea serializado y deserializado. En otras palabras, la instancia M concreta no es solo una clase de datos. Tiene un comportamiento específico. – AnthonyF
Con deserialization/umarshaling, debe colocar la implementación fuera de la clase porque el objeto aún no existe. He demostrado una forma de implementar esto usando typeclass, pero también puedes hacer esto usando un objeto complementario si quieres. –