2010-11-01 69 views
9

我正在玩這個例子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 

我的例子停止工作。更詳細地說,雖然case對象是可序列化的,但case類不是。事實上,當我嘗試這最後修改我得到下面的異常運行我的例子:

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

有原因的情況下對象可以進行序列化和案例類不能理由嗎?有沒有辦法讓我的例子與案例類一起工作?

編輯:由Victor建議並由Aaron確認我將伴侶對象作爲消息而不是類發送。此外檢查與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 

現在的問題是:我怎麼可以指定我想使用類而不是伴侶對象?當我按照Aaron的建議發送郵件時,我還添加了一對空括號。

pong ! Ping() 

但是沒有任何更改。最後,我還添加了假參數的情況下類

case class Ping(i: Int) extends Event 

發送消息爲:

pong ! Ping(0) 

但沒有遇到任何差異仍然。任何建議?

+2

據我所知,你不需要明確地實現'Serializable'接口,因爲case類和case對象都已經隱含地使用了'@ serializable'(它只是被提了出來)。用'scalac -print'編譯你的代碼來查看剝離的代碼 - 它可以幫助你找出問題所在。 REPL中的一個小測試表明,案例類可以在2.8.0版中[反序列化]。 – 2010-11-01 10:17:07

+0

http://gist.github.com/657953 – 2010-11-01 10:26:47

+0

http://scala-programming-language.1934581.n4.nabble.com/deprecate-serializable-td3002109。html – 2010-11-01 10:36:27

回答

14
@serializable case class Foo 

我還驚訝的發現,案件對象在默認情況下是可序列化的。

編輯:看完後除了正常我懷疑:

您正在嘗試發送的情況下階級的產生的配對對象通過線路,而不是案件類的一個實例。

+9

案例類也是默認可序列化的。順便說一句,在上面的代碼片段中,從「Serializable」繼承的案例類在大多數情況下等於使用「@ serializable」註釋 – 2010-11-01 12:43:58

+7

通常,不推薦使用「@ serializable」,它可能很快就會被棄用: http://scala-programming-language.1934581.n4.nabble.com/deprecate-serializable-td3002109.html – 2010-11-01 12:46:13

+0

對不起,但我認爲你沒有迴應我的問題。 @serializable註解和擴展Serializable接口應該幾乎相同(即使第一個顯然將被棄用)無論如何我也試圖使用@serializable註釋,並且我經歷了相同的效果:case對象可以被序列化而案例類不能。換句話說,即使編寫@serializable case class Ping在我的示例中也不起作用。 – 2010-11-01 15:52:41

4

沒有參數的案例類沒有意義,並且不推薦使用。我在Scala看到沒有Serializable,只有serializable。如果你解決這些問題,它會起作用嗎?

+2

我想要使用大小寫類,因爲我需要向它們添加一些參數。 Serializable接口實際上是java.io包中的接口,並且使用@serializable註釋也是一樣的,並給出了我經歷的同樣的問題。此外,對於我所知道的@serializable註釋將被棄用,這是我避免使用它的唯一原因。 – 2010-11-01 16:00:52

+0

@Mario我的意思是擴展scala.serializable,這是推薦的方式。 – 2010-11-01 20:39:39