Scala のプレイフレームワークのチュートリアルを進めていたところ、次のようなコード スニペットに遭遇し、困惑しました。
def newTask = Action { implicit request =>
taskForm.bindFromRequest.fold(
errors => BadRequest(views.html.index(Task.all(), errors)),
label => {
Task.create(label)
Redirect(routes.Application.tasks())
}
)
}
そこで調べてみたところ、この郵便受け。
まだ分かりません。
以下の違いは何でしょうか:
implicit def double2Int(d : Double) : Int = d.toInt
そして
def double2IntNonImplicit(d : Double) : Int = d.toInt
メソッド名が異なるという明白な事実を除けば。
いつ、なぜ使用すればよいのでしょうかimplicit
?
ベストアンサー1
以下に暗黙的な主な使用例を説明しますが、詳細についてはScalaプログラミングの関連章。
暗黙のパラメータ
メソッドの最後のパラメータ リストは とマークできますimplicit
。これは、値が呼び出されたコンテキストから取得されることを意味します。スコープ内に適切な型の暗黙的な値がない場合、コンパイルされません。暗黙的な値は単一の値に解決される必要があり、衝突を避けるため、目的に応じて型を固有にすることをお勧めします。たとえば、メソッドが暗黙的な を見つける必要がないようにしますInt
。
例:
// probably in a library
class Prefixer(val prefix: String)
def addPrefix(s: String)(implicit p: Prefixer) = p.prefix + s
// then probably in your application
implicit val myImplicitPrefixer = new Prefixer("***")
addPrefix("abc") // returns "***abc"
暗黙的な変換
コンパイラは、コンテキストに対して間違った型の式を見つけると、Function
型チェックを可能にする型の暗黙的な値を探します。したがって、 がA
必要で が見つかった場合B
、スコープ内で型の暗黙的な値を探します(やコンパニオン オブジェクトB => A
など、他の場所もチェックします (存在する場合))。はオブジェクトに「イータ展開」できるため、も同様に機能します。B
A
def
Function
implicit def xyz(arg: B): A
したがって、メソッド間の違いは、が見つかったが が必要なimplicit
場合、マークされたメソッドがコンパイラによって挿入されることです。Double
Int
implicit def doubleToInt(d: Double) = d.toInt
val x: Int = 42.0
同じように動作します
def doubleToInt(d: Double) = d.toInt
val x: Int = doubleToInt(42.0)
2 番目では手動で変換を挿入しましたが、1 番目ではコンパイラが自動的に同じことを行いました。左側の型注釈のために変換が必要です。
Play からの最初のスニペットについて:
アクションについては、このページPlayのドキュメントから(APIドキュメント)。
apply(block: (Request[AnyContent]) ⇒ Result): Action[AnyContent]
オブジェクト上Action
(同じ名前の特性の仲間です)。
したがって、引数として関数を指定する必要があります。これは、次の形式のリテラルとして記述できます。
request => ...
関数リテラルでは、 の前の部分は=>
値宣言であり、implicit
他の宣言と同様に、必要に応じてマークすることができますval
。ここでは、は型チェックのためにマークする必要はありrequest
ませんimplicit
が、そうすることで、関数内でそれを必要とする可能性のあるメソッドの暗黙の値として利用できるようになります(もちろん、明示的に使用することもできます)。この特定のケースでは、 のbindFromRequest
メソッドが形状クラスには暗黙のRequest
引数が必要です。