Расширение абстрактных удаленных актеров и сопоставление с образцом (ClassLoading?) В Scala

Я реализую некоторые абстрактные классы, которые расширяют Actor и предоставляют дополнительную функциональность [1]. Тем не менее, сопоставление с образцом, кажется, не работает в операторах приема. Если я отправляю объект дела 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и сериализует точно так же ByteArray с помощью ObjectOutputStream а также writeObject, но не равно этому (используя ==). Мое лучшее предположение, что 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
  }
}

Когда я запускаю эту программу, вывод такой же, как указано выше. Connect сообщение получено удаленно от MyWorker не был распознан сопоставлением с образцом в методе действия MyMaster, Даже если getClass.toString оценивает одно и то же на них, они как-то не совпадают. Как я могу это исправить?

[1] Подробнее: я реализую среду для определенного вида параллельных вычислений на большом количестве узлов. В более сложном случае я бы хотел заменить ConnectionTest с ParallelComputation[Data, Result] где Data а также Result являются параметрами типа. Сообщение также будет включать в себя классы, которые зависят от этих параметров, таких как

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

В идеале я хотел бы, чтобы решение, которое хорошо сочеталось с этим шаблоном дизайна.

1 ответ

Решение

Я не проверял, но я думаю, что вы не должны ставить свои Message черта и реализации (включая объект Connect) в классе ConnectionTest, Вы можете поместить их в объект-компаньон. Если вы поместите их в класс, есть отдельный объект Connect для каждого экземпляра содержащего класса ConnectionTest (и что еще хуже в контексте сериализации, он имеет ссылку на этот экземпляр).

объекты Connect принадлежность к разным экземплярам ConnectionTest различна и не соответствует друг другу.

Другие вопросы по тегам