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