2015-12-07 8 views
6

私はScalaをかなり新しくしており、暗黙的な変換とパラメータを習得して理解しようとしており、混乱するシナリオに遭遇しました。Scalaの暗黙の抽象クラスコンストラクタパラメータと継承

私はScaldiを使ってAkkaアプリケーションに依存性注入を行い、複数の注射可能なアクターに抽象クラスを継承させたいと考えています。フレームワークを利用するためには、暗黙的にコンストラクタ引数を使用してInjectorを利用する必要があるため、抽象クラスを正確に特性にすることはできません。次のように私は見てい挙動を示す

非常に不自然な例は次のとおりです。

class SecretSauce {} 

abstract class Base(implicit secretSauce: SecretSauce) {} 

class Concrete extends Base {} 

object Example extends App { 
    ... // Setup Actor system, etc, etc 
    implicit val secretSauce: SecretSauce = new SecretSauce() 
} 

私は仕事をする事を期待していたが、代わりに、私はコンパイルエラーを取得:

Unspecified value parameter secretSauce. 
class Concrete extends Base { 
      ^

もしI具体的なクラスに暗黙のパラメータを追加すると、そのようなものが動作します:

class Concrete(implicit secretSauce: SecretSauce) extends Base {} 

私の混乱は、暗黙的なパラメータがどのように機能するかに起因しています。私が説明しているような状況では、子クラスに継承されていませんか?誰かが私の例で何が起こっているのか、それを明確にするのに役立つ参考資料を指摘できますか?

ありがとうございます!

答えて

2

Scalaのコンパイラが暗黙を検索する場所を決定正確な規則は一種の複雑であるが、ほとんどの状況であなただけの暗黙の値がから来ることができる2つの場所を考える必要があります:

  1. 現在のスコープ。
  2. 任意のタイプのコンパニオンオブジェクト。

これは、これがコンパイルされます意味:

class SecretSauce {} 

object SecretSauce { 
    implicit val secretSauce: SecretSauce = new SecretSauce() 
} 

abstract class Base(implicit secretSauce: SecretSauce) {} 

object Example extends App { 
    class Concrete extends Base {} 
} 

またはこの:

class SecretSauce {} 

abstract class Base(implicit secretSauce: SecretSauce) {} 

object Example extends App { 
    implicit val secretSauce: SecretSauce = new SecretSauce() 

    class Concrete extends Base {} 
} 

をお使いのバージョンでは、しかし、コンパイラは、この行を取得するとき:

class Concrete extends Base {} 

それは暗黙のうちにSecretSauce vaを見つける必要があることを知るでしょう最初に、その行のの暗黙の値をに、次にSecretSauce(存在する場合)の暗黙の値を調べます。それも見つからないので、コードをコンパイルすることを拒否します。

+0

ああ、私はルールの蒸留がかなり助けてくれたと思います。具体的なクラスで暗黙の引数が重複している場合にコンパイルエラーがスローされないのはなぜですか? 私のコードで設定した方法から、暗黙的な値は依然として有効範囲内でも、コンパニオンオブジェクト内にもありませんか?スコープについての私の理解はここにありますか? – simonl

+0

@simonl暗黙的なパラメータを 'Concrete'コンストラクタに追加すると、それは暗黙的に親コンストラクタの呼び出しのスコープに入ります。クラス定義とコンストラクタのためのScalaの構文は、これを少し直感的にしますが、うまくいきます。 –

1

暗黙のパラメータがから「解決」を取得:限り、私は理解してclass Concreteを定義するために、現在のスコープで定義された

  • 暗黙
  • 明示的な輸入
  • ワイルドカード輸入

暗黙的に定義またはインポートする必要があります。

this SO answerで非常に良い説明が見つかりました。

関連する問題