Girando Attori Scala ad attori Akka: un caso di chiamare metodi su
Domanda
Recentemente sono stato il passaggio da attori Scala Akka attori, ma notato che Akka attori usano ActorRef
invece dell'oggetto esempio:
val actorRef: ActorRef = Actor.actorOf(new MyActor)
Così ho provato:
val myActor = new MyActor
val actorRef: ActorRef = Actor.actorOf(x)
... di avere sia: 1) ActorRef
per inviare messaggi e 2) MyActor
ai metodi call su
.
Ma ho ottenuto:
akka.actor.ActorInitializationException: ActorRef for instance of actor [MyActor] is not in scope.
Quindi la mia domanda è: Come posso ottenere un'istanza (di un certo tipo) su cui posso chiamare ActorRef
simili metodi come !
e anche metodi dall'istanza MyActor
Soluzione
Quello che stai facendo è un terribile idea. Quindi, semplicemente smettere proprio adesso, passo dalla tastiera, e andare a l'Akka Documentazione e leggere su attori.
Considerate questo:
class YourActor extends Actor {
var mutableStuff = ...
def receive = {
case _ =>
// mess with mutableStuff
}
def publicMethod = // mess with mutableStuff
}
Ora, impostare il sistema e iniziare a inviare messaggi e chiamare quel metodo da altri thread. Boom!
Si sta facendo appunto che cosa Akka e il modello attore aiutare a prevenire. Si sta effettivamente facendo in quattro per rompere quello che hanno già fissato :) Loro non ti consente di farlo.
Ora, è possibile test di unità accedendo direttamente i metodi ma è necessario un TestActorRef per questo. Mentre si sta leggendo la documentazione, leggere la sezione Testing.
Altri suggerimenti
Il meglio che posso in mente è il seguente, piuttosto sporco:
C'è un modo migliore?
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