12

この例http://scala.sygneca.com/code/remoteactorsで遊んで、リモート アクターが Scala (2.8.0) でどのように機能するかを学びます。特に、アクターによって送信されるメッセージが次のように定義される方法を少し変更しました。

sealed trait Event extends Serializable
case object Ping extends Event
case object Pong extends Event
case object Quit extends Event

すべてが期待どおりに機能します。残念ながら、イベントをケース オブジェクトではなくケース クラスとして定義すると、次のようになります。

sealed trait Event extends Serializable
case class Ping extends Event
case class Pong extends Event
case class Quit extends Event

私の例は動作を停止します。より詳細には、ケース オブジェクトは直列化可能ですが、ケース クラスは直列化できないようです。実際、この最後の変更で例を実行しようとすると、次の例外が発生します。

scala.actors.remote.DelegateActor@148cc8c: 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)

ケース オブジェクトをシリアライズ可能にできるのに、ケース クラスをシリアライズできない理由はありますか? 私の例をケースクラスで動作させる方法はありますか?

編集:ビクターが提案し、アーロンが確認したように、クラスではなくメッセージとしてコンパニオンオブジェクトを送信しています。さらに、コンパイルされたコードを javap で調べると、クラスがシリアライズ可能であることが明らかです。

public class scalachat.remote.Ping extends java.lang.Object implements scalachat.remote.Event,java.io.Serializable,scala.ScalaObject,scala.Product

コンパニオン オブジェクトは次のとおりではありません。

public final class scalachat.remote.Ping$ extends scala.runtime.AbstractFunction0 implements scala.ScalaObject

問題は、コンパニオン オブジェクトの代わりにクラスを使用するように指定するにはどうすればよいかということです。次のように、アーロンが提案したようにメッセージを送信するときに、空の括弧も追加しました。

pong ! Ping()

しかし、何も変更されていません。最後に、ケースクラスに偽のパラメーターも追加しました

case class Ping(i: Int) extends Event

次のようにメッセージを送信します。

pong ! Ping(0)

しかし、まだ何の違いも経験していません。なにか提案を?

4

2 に答える 2

15
@serializable case class Foo

ケース オブジェクトがデフォルトでシリアライズ可能であることにも驚きました。

編集:例外を適切に読んだ後、次のように思われます:

ケース クラスのインスタンスではなく、ケース クラスの生成されたコンパニオン オブジェクトをネットワーク経由で送信しようとしています。

于 2010-11-01T12:34:04.970 に答える
4

パラメータのないケースクラスは無意味であり、非推奨です。そしてSerializable、Scalaには何も表示されませんserializable。これらを修正すれば機能しますか?

于 2010-11-01T14:07:16.163 に答える