Juego con este ejemplo http://scala.sygneca.com/code/remoteactors para aprender cómo funcionan los actores remotos en Scala (2.8.0). En particular modifiqué ligeramente cómo los mensajes enviados por los actores se definen como sigue:¿Por qué no se pueden serializar objetos y clases de casos?
sealed trait Event extends Serializable
case object Ping extends Event
case object Pong extends Event
case object Quit extends Event
y todo funciona como se esperaba. Desafortunadamente si defino los eventos como clases de casos en lugar de objetos de casos como en:
sealed trait Event extends Serializable
case class Ping extends Event
case class Pong extends Event
case class Quit extends Event
mi ejemplo deja de funcionar. En más detalle, parece que, aunque los objetos del caso son serializables, las clases de casos no lo son. De hecho, cuando trato de ejecutar mi ejemplo con esta última modificación consigo la siguiente excepción:
[email protected]: caught java.io.NotSerializableException: scalachat.remote.Ping$
java.io.NotSerializableException: scalachat.remote.Ping$
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1156)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:326)
at scala.actors.remote.JavaSerializer.serialize(JavaSerializer.scala:46)
at scala.actors.remote.NetKernel.namedSend(NetKernel.scala:38)
at scala.actors.remote.NetKernel.forward(NetKernel.scala:71)
at scala.actors.remote.DelegateActor$$anonfun$act$1$$anonfun$apply$1.apply(Proxy.scala:182)
at scala.actors.remote.DelegateActor$$anonfun$act$1$$anonfun$apply$1.apply(Proxy.scala:123)
at scala.actors.ReactorTask.run(ReactorTask.scala:34)
at scala.actors.ReactorTask.compute(ReactorTask.scala:66)
at scala.concurrent.forkjoin.RecursiveAction.exec(RecursiveAction.java:147)
at scala.concurrent.forkjoin.ForkJoinTask.quietlyExec(ForkJoinTask.java:422)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.mainLoop(ForkJoinWorkerThread.java:340)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:325)
¿Hay una razón por qué los objetos de casos se pueden hacer clases serializables y casos no se puede? ¿Hay alguna forma de que mi ejemplo funcione con clases de casos?
Editar: según lo sugerido por Victor y confirmado por Aaron, estoy enviando el objeto complementario como mensaje en lugar de la clase. Además de inspeccionar el código compilado con javap parece evidente que mientras que la clase es serializable:
public class scalachat.remote.Ping extends java.lang.Object implements scalachat.remote.Event,java.io.Serializable,scala.ScalaObject,scala.Product
el objeto compañero no es:
public final class scalachat.remote.Ping$ extends scala.runtime.AbstractFunction0 implements scala.ScalaObject
Ahora la pregunta es: ¿Cómo puedo especificar que quiero usar la clase en lugar del objeto compañero? También agregué un par de paréntesis vacíos cuando envío el mensaje sugerido por Aaron como en:
pong ! Ping()
pero nada ha cambiado. Al final me También se ha añadido un parámetro falso a la clase caso
case class Ping(i: Int) extends Event
enviando el mensaje como:
pong ! Ping(0)
pero sin experimentar ninguna diferencia todavía. ¿Cualquier sugerencia?
Por lo que yo sé, no es necesario implementar explícitamente la interfaz 'Serializable', ya que ambas clases de casos y objetos de caso ya están implícitamente usando' @ serializable' (es simplemente azucarado). Compila tu código con 'scalac -print' para ver el código eliminado, puede ayudarte a descubrir cuál es el problema. Una pequeña prueba en el REPL muestra que las clases de casos pueden ser [deserializadas] contra 2.8.0. –
http://gist.github.com/657953 –
http://scala-programming-language.1934581.n4.nabble.com/deprecate-serializable-td3002109.html –