我正在实现一些抽象类,它们扩展了Actor并提供了一些额外的功能[1]。然而,模式匹配似乎在receive语句中不起作用。如果我从客户端发送一个case对象Connect
到服务器,并且在服务器中有一个模式匹配的表单:
println("Starting to receive, e.g. " + Connect.getClass.toString)
receive {
case Connect => println("Got a connected message")
case m => println("Got something weird: " + m + " of type " + m.getClass.toString)
}
则输出为
Starting to receive, e.g. class ConnectionTest$Connect$
Got something weird: Connect of type class ConnectionTest$Connect$
...
传入消息在模式匹配中没有被识别为Connect
对象,即使getClass说它是。更奇怪的是:m
与Connect
具有相同的hashCode,并且使用ObjectOutputStream
和writeObject
序列化为完全相同的ByteArray
,但不等于它(使用==
)。我最好的猜测是classLoader的行为不正确,但我很困惑。
下面是我想写的一个更完整的例子:
import scala.actors.{Actor, OutputChannel}
import scala.actors.Actor._
import scala.actors.remote.RemoteActor
import scala.actors.remote.RemoteActor._
import scala.actors.remote.Node
abstract class ConnectionTest(masterNode: Node, port: Int) {
trait Message
case object Connect extends Message
abstract class Master extends Actor {
def act {
RemoteActor.classLoader = getClass.getClassLoader
alive(port)
register('MasterProcess, self)
while (true) {
println("Starting to receive, e.g. " + Connect.getClass.toString)
receive {
case Connect => println("Got a connect message")
case m => println("Got something weird: " + m + " of type " + m.getClass.toString)
}
}
}
}
abstract class Worker extends Actor {
def act {
RemoteActor.classLoader = getClass.getClassLoader
val master = select(masterNode, 'MasterProcess)
link(master)
master ! Connect
}
}
}
下面是一个例子:
object MyConnectionApp extends optional.Application {
case class MyConTest(hostname: String, port: Int) extends ConnectionTest(Node(hostname, port), port) {
case object MyMaster extends Master
case object MyWorker extends Worker
}
def main(master: Boolean) = {
if (master)
MyConTest("localhost", 2552).MyMaster start
else
MyConTest("localhost", 2552).MyWorker start
}
}
当我运行这个程序时,输出如下所示。MyMaster
的行为方法中的模式匹配不能识别远端从MyWorker
接收到的Connect
消息。尽管getClass.toString
对它们的计算结果相同,但它们在某种程度上是不相同的。我该如何解决这个问题?
[1]更多细节:我正在实现一个框架,用于跨大量节点的某种并行计算。在更复杂的情况下,我实际上想用ParallelComputation[Data, Result]
替换ConnectionTest
,其中Data
和Result
是类型参数。Message还将包括依赖于这些参数的类,如
case object Computed(x: Data, y: Result) extends Message
理想情况下,我希望有一个解决方案,可以很好地发挥这种设计模式。
我没有测试过,但我认为你不应该把你的Message
trait和实现(包括对象Connect
)放在ConnectionTest
类中。你可以把它们放在同伴对象中。如果将它们放在一个类中,则对于包含类ConnectionTest
的每个实例,都有一个不同的对象Connect
(更糟糕的是,在序列化上下文中,它有对该实例的引用)。
对象Connect
属于不同的ConnectionTest实例是不同的,彼此不匹配