Scalaでは暗黙的に次のように機能します:
コンバータ
パラメータ値インジェクター
拡張方法
Implicitにはいくつかの用途があります
暗黙的な型変換:エラーを生成する割り当てを目的の型に変換します
val x :String = "1"
val y:Int = x
文字列はIntのサブタイプではないため、2行目でエラーが発生します。エラーを解決するために、コンパイラはスコープ内で暗黙のキーワードを持ち、引数として文字列を取り、 Intを返すそのようなメソッドを探します。
それで
implicit def z(a:String):Int = 2
val x :String = "1"
val y:Int = x // compiler will use z here like val y:Int=z(x)
println(y) // result 2 & no error!
暗黙的な受信者変換:通常、受信者はオブジェクトのプロパティを呼び出します。メソッドまたは変数。したがって、レシーバーによってプロパティを呼び出すには、プロパティがそのレシーバーのクラス/オブジェクトのメンバーである必要があります。
class Mahadi{
val haveCar:String ="BMW"
}
class Johnny{
val haveTv:String = "Sony"
}
val mahadi = new Mahadi
mahadi.haveTv // Error happening
ここで、 mahadi.haveTvはエラーを生成します。Scalaコンパイラは最初にmahadiレシーバーへのhaveTvプロパティを探すからです。見つかりません。次に、 Mahadiオブジェクトを引数として取り、 Johnnyオブジェクトを返す暗黙のキーワードを持つスコープ内のメソッドを探します。しかし、ここにはありません。したがって、エラーが発生します。しかし、以下は大丈夫です。
class Mahadi{
val haveCar:String ="BMW"
}
class Johnny{
val haveTv:String = "Sony"
}
val mahadi = new Mahadi
implicit def z(a:Mahadi):Johnny = new Johnny
mahadi.haveTv // compiler will use z here like new Johnny().haveTv
println(mahadi.haveTv)// result Sony & no error
暗黙的なパラメータインジェクション:メソッドを呼び出し、そのパラメータ値を渡さないと、エラーが発生します。Scalaコンパイラーはこのように機能します-最初に値を渡そうとしますが、パラメーターの直接値を取得しません。
def x(a:Int)= a
x // ERROR happening
次に、パラメーターに暗黙のキーワードがある場合、同じタイプの値を持つスコープ内の任意のvalを検索します。取得しない場合はエラーが発生します。
def x(implicit a:Int)= a
x // error happening here
この問題を解決するために、コンパイラーは、パラメーターaに暗黙のキーワードが含まれているため、 Intの型を持つ暗黙のvalを探します。
def x(implicit a:Int)=a
implicit val z:Int =10
x // compiler will use implicit like this x(z)
println(x) // will result 10 & no error.
もう一つの例:
def l(implicit b:Int)
def x(implicit a:Int)= l(a)
私たちはそれを次のように書くこともできます-
def x(implicit a:Int)= l
lには暗黙のパラメーターがあり、メソッドxの本体のスコープには、xのパラメーターである暗黙のローカル変数(パラメーターはローカル変数)aがあります。したがって、xメソッドの本体には 、メソッド署名lの暗黙の引数値は次のようになります。 xメソッドのローカル暗黙変数(パラメーター)によって暗黙的にファイルされます。a
それで
def x(implicit a:Int)= l
このようなコンパイラになります
def x(implicit a:Int)= l(a)
もう一つの例:
def c(implicit k:Int):String = k.toString
def x(a:Int => String):String =a
x{
x => c
}
x {x => c}のcは、引数の明示的な値の受け渡しまたはスコープの暗黙のvalを必要とするため、エラーが発生します。
したがって、メソッドxを呼び出すときに、関数リテラルのパラメーターを明示的に暗黙的にすることができます。
x{
implicit x => c // the compiler will set the parameter of c like this c(x)
}
これはPlay-Frameworkのアクションメソッドで使用されています
in view folder of app the template is declared like
@()(implicit requestHreader:RequestHeader)
in controller action is like
def index = Action{
implicit request =>
Ok(views.html.formpage())
}
リクエストパラメータを明示的に暗黙的に言及していない場合は、次のように記述されている必要があります-
def index = Action{
request =>
Ok(views.html.formpage()(request))
}
- 拡張方法
Integerオブジェクトを使用して新しいメソッドを追加したいと考えてください。メソッドの名前はmeterToCmになります。
> 1 .meterToCm
res0 100
これを行うには、オブジェクト/クラス/トレイト内に暗黙のクラスを作成する必要があります。このクラスをケースクラスにすることはできません。
object Extensions{
implicit class MeterToCm(meter:Int){
def meterToCm={
meter*100
}
}
}
暗黙のクラスは1つのコンストラクターパラメーターのみを受け取ることに注意してください。
次に、使用するスコープに暗黙のクラスをインポートします
import Extensions._
2.meterToCm // result 200