Расширение абстрактных удаленных актеров и сопоставление с образцом (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 различна и не соответствует друг другу.