Actuar los actores de Scala a los actores de Akka: una instancia para llamar a los métodos en

StackOverflow https://stackoverflow.com/questions/9311780

  •  26-10-2019
  •  | 
  •  

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?

¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top