在Scala中扩展抽象远程角色和模式匹配(类加载?)



我正在实现一些抽象类,它们扩展了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说它是。更奇怪的是:mConnect具有相同的hashCode,并且使用ObjectOutputStreamwriteObject序列化为完全相同的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,其中DataResult是类型参数。Message还将包括依赖于这些参数的类,如

case object Computed(x: Data, y: Result) extends Message

理想情况下,我希望有一个解决方案,可以很好地发挥这种设计模式。

我没有测试过,但我认为你不应该把你的Message trait和实现(包括对象Connect)放在ConnectionTest类中。你可以把它们放在同伴对象中。如果将它们放在一个类中,则对于包含类ConnectionTest的每个实例,都有一个不同的对象Connect(更糟糕的是,在序列化上下文中,它有对该实例的引用)。

对象Connect属于不同的ConnectionTest实例是不同的,彼此不匹配

最新更新