Actuar los actores de Scala a los actores de Akka: una instancia para llamar a los métodos en
Pregunta
Recientemente estaba cambiando de actores de Scala a actores de Akka, pero noté que los actores de Akka usan ActorRef
En lugar del objeto de instancia:
val actorRef: ActorRef = Actor.actorOf(new MyActor)
Entonces lo intenté:
val myActor = new MyActor
val actorRef: ActorRef = Actor.actorOf(x)
... para tener ambos: 1) ActorRef
Para enviar mensajes y 2) MyActor
Para llamar a los métodos.
Pero tengo:
akka.actor.ActorInitializationException: ActorRef for instance of actor [MyActor] is not in scope.
Entonces mi pregunta es: ¿cómo puedo obtener una instancia (de algún tipo) en la que puedo llamar ActorRef
-Se -similar a métodos como !
Y también métodos del MyActor
¿instancia?
Solución
Lo que estás haciendo es un horrible ocurrencia. Así que pare ahora mismo, aléjate del teclado y ve a la documentación de Akka y leer sobre actores.
Considera esto:
class YourActor extends Actor {
var mutableStuff = ...
def receive = {
case _ =>
// mess with mutableStuff
}
def publicMethod = // mess with mutableStuff
}
Ahora, configure su sistema y comience a enviar mensajes y llame a ese método desde otros hilos. ¡Auge!
Estás haciendo precisamente Lo que Akka y el modelo de actor te ayudan a prevenir. En realidad, te estás inclinando hacia atrás para romper lo que ya han arreglado :) No te dejarán hacerlo.
Ahora, puede realizar una prueba unitaria accediendo directamente, pero necesita un TestActorRef para eso. Mientras lee los documentos, lea la sección sobre pruebas.
Otros consejos
Lo mejor que puedo hacer es lo siguiente, bastante sucio:
¿Hay una mejor manera?
import akka.actor._
trait ActorCom {
var actorRefForInitialization: ActorRef = _
lazy val actorRef: ActorRef = actorRefForInitialization
def ?(message: Any)(implicit channel: UntypedChannel = NullChannel, timeout: Actor.Timeout = Actor.defaultTimeout) = actorRef ? message
def !(msg: Any)(implicit sender: UntypedChannel) = actorRef ! msg
def start = actorRef.start
}
object AkkaActorFactory {
def apply[A <: Actor](newInstance: => A with ActorCom): A with ActorCom = {
var instance: Option[A with ActorCom] = None
val actorRef = Actor.actorOf({
instance = Some(newInstance)
instance.get
})
instance.get.actorRefForInitialization = actorRef
instance.get.actorRef // touch lazy val in ActorCom, to make it equal to actorRef and then its fixed (immutable)
instance.get
}
}
class MyActor extends Actor {
def receive = {
case "test1" => println("good")
case "test2" => println("fine")
case _ => println("bad")
}
def sendTestMsg2Myself = self ! "test2"
}
val myActor = AkkaActorFactory(newInstance = new MyActor with ActorCom)
myActor.start
myActor ! "test1"
myActor.sendTestMsg2Myself // example for calling methods on MyActor-instance
myActor ! PoisonPill