2017-05-13 6 views
0

ActorSystemをServiceAServiceBで利用できるようにするにはどうすればよいですか?これは動作しようとしているコードです。それはコンパイルしますが、私はTcpで暗黙的なシステムのnullポインタ例外を取得します。Scalaの暗黙的なAkkaシステムの特性

nullpointer例外が発生するのはなぜですか。 システムを自分の特性サービスに追加するにはどうすればよいですか?なぜそれはコンパイルされますか? (systemを使用)SystemASystemB

trait ServiceA { 
    implicit val system: ActorSystem 
} 

trait ServiceB { 
    implicit val system: ActorSystem 
    Tcp().outgo... // Code compile but i get nullpointer exception 
} 

object Main extends App with ServiceA with ServiceB { 
    override implicit val system: ActorSystem = ActorSystem("MySys") 
} 
+0

は、第2の形質特色ServiceBですか? –

+0

入力ミスが修正されました。 – user3139545

+0

TCPの定義を特質Bに投稿できますか?それはどこでヌルポインタを投げますか?それが呼び出されたMainからのMainコード –

答えて

4

コンストラクタはsystemの初期化を含むMainのコンストラクタの前に実行されます。 implicit lazy val system = ...Mainに使用してください(このように抽象度valを実装することが許可されています)。この問題は修正する必要があります。

+0

この慣用的なScalaはありますか?私は本当に形質を使うのが好きです。 – user3139545

+0

'val'を遅延させたくない場合は、' main Maintain App {override val system = ActorSystem( "MySys")}のようなイニシャライザブロックをServiceB {} 'のServiceAで使うこともできると思います。 –

0

@alexei_romanovによる回答 に加えて、 valまたはdefに割り当てずに、Tcp...コールを特性本体に配置することで、何を達成したいですか?それは今やMainの初期化中のある瞬間に実行されるアクションです。まだ初期化されていないオブジェクトのアクションなので、未定義のビヘイビアを呼び出すことができます。

+0

はい、悪い例でしたが、私のポイントを示すために最小限のコードを書こうとしました。 – user3139545

+0

"これは未定義のビヘイビアになる"いいえ、できません。これは完全に明確です。 –

+0

あなたは正しいです、予期しないと言うのは良いです。 – simpadjo

0

これは形質の初期化の順序に起因しており、実際には型システムがこれを守ることができないのは残念です。これを解決する

1つのオプションは、独自の特性にActorSystemの初期化を入れて、1が最初に混入することを確認することですので、:

trait ServiceA { 
    implicit val system: ActorSystem 
} 

trait ServiceB { 
    implicit val system: ActorSystem 
    Tcp().outgo... // Code compile but i get nullpointer exception 
} 

trait ActorSystemInitialization { 
    val system: ActorSystem = ActorSystem("MySys") 
} 

object Main extends App with ActorSystemInitialization with ServiceA with ServiceB { 

} 
関連する問題