2012-02-16 10 views
3

のメソッドを呼び出すために1つのインスタンスは、最近、私はアッカ役者にScalaの俳優からの切り替えが、アッカの俳優ではなく、インスタンスオブジェクトのActorRefを使用していることに気づいた。はAkkaの俳優にScalaのアクターを回す:

val actorRef: ActorRef = Actor.actorOf(new MyActor) 

だから私が試しました:

val myActor = new MyActor 
val actorRef: ActorRef = Actor.actorOf(x) 

は...両方を持っている:1)ActorRefメッセージを送信すると、2)MyActor上のメソッドを呼び出すこと。
しかし、私が得た:

akka.actor.ActorInitializationException: ActorRef for instance of actor [MyActor] is not in scope. 

だから私の質問です:私はMyActorインスタンスから!も方法のようにActorRef様のメソッドを呼び出すことができた上で(いくつかのタイプの)インスタンスを取得するにはどうすればよいですか?

+0

なぜあなたは俳優のメソッドを呼び出していますか?どのような方法ですか?私は俳優に直接メソッドを呼び出すことは危険だと思うでしょうし、あなたはこれがどのように動作するかについて考えるべきです。 – Submonoid

+0

@Submonoid私は危険なことを知っています。私の例では、アクターの内部状態(危険な部分)は変更されませんが、メッセージを送信するだけであることがわかります。 –

答えて

14

ひどい考えです。だからちょうど今すぐ停止し、キーボードから離れてthe Akka Documentationに行き、俳優を読んでください。

はこのことを考えてみましょう:今、

class YourActor extends Actor { 
    var mutableStuff = ... 
    def receive = { 
    case _ => 
     // mess with mutableStuff 
    } 
    def publicMethod = // mess with mutableStuff 
} 

をお使いのシステムを設定し、メッセージを送信し、他のスレッドからそのメソッドを呼び出しを開始します。ブーム!

あなたはを正確にとしています。アクカと俳優のモデルがあなたを防ぐのを助けるもの。あなたは実際に彼らがすでに修正したことを壊すために後方に曲がっています:)彼らはあなたにそれをさせません。

ここで、メソッドに直接アクセスすることで単体テストできますが、そのためにはTestActorRefが必要です。ドキュメントを読んでいる間は、テストのセクションを読んでください。

+0

物事を明確にしてくれてありがとう。私は、それが 'ActorRef'が存在する理由(他の事実の他に、例えば、ネットワークを介して送信するためのそのシリアライズ可能なもの)も存在すると考えます。アクターの変更可能な部分を変更したいと思っていません。これは危険です(別のスレッドから呼び出されたとき)、私は知っています。これは便宜的な方法であるにすぎません。しかし、私はアクターモデルを破る代わりに別のアプローチをとるべきです。 –

+0

私はそれを得るが、それは方法ではない。 Akkaは単なるツールキットではなく、同時に実行するフォールトトレラントなプログラミングのパラダイムです。あなたが構築しているものは、本当にカードの家です。いくつかのジョーカーがどこかより良い、突然変異した状態を知らない限り、それは "便利"でしょう。あなたがしたことは、「開かないでください」という看板が付いた地獄に鍵をかけられていない扉が置かれているだけです。 –

+0

いいアナロジー。私はそれぞれのジョーカーであることを恐れています。D –

1

私ができる最大のものは、以下のものです。かなり汚れています。
良い方法がありますか?何をやっている

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 
関連する問題