2016-08-15 10 views
2

暗黙パラメーターがどこから来るのかを理解しようとしています。ここでは、ジェネリック型の制約の暗黙的な解像度の簡単なデモです:スカラーのかっこなしのメソッド呼び出し(暗黙的なパラメーター付き)

class ImplicitTypeConstraint[+T](val t : T) { 
    def doSome1(implicit ev: T <:< Int) = println("Int value = " + ev(t)) 
    def doSome2(implicit ev: T <:< Int, u : Unit) = println("Int value = " + ev(t)) 
    def doSome3(u : Unit)(implicit ev: T <:< Int) = println("Int value = " + ev(t)) 
} 

は今、私はこの

val itc = new ImplicitTypeConstraint(10) 
itc.doSome1 //compiles fine 
itc.doSome1() //compile error, Cannot resolve reference doSome1 with such signature 

itc.doSome2 //compile error, not enough arguments for method doSome2 
itc.doSome2() //compile error, Cannot resolve reference doSome2 with such signature 

itc.doSome3 //compile error, Cannot resolve reference doSome3 with such signature 
itc.doSome3() //compiles fine 

をしようとした質問がdoSome1doSome2の署名の違いは何であるか、ですか?私はJavaから来て、私は、foo()は、の明示的なのパラメータを持っていない関数を呼び出すと思っていましたが、それはタイプUnitの1つのパラメータを持つ関数を探しているようです。

UPD:Itellijはプロジェクトを明示的にビルドする前にエラーを表示しませんでした。 doSome2()doSome2はコンパイルを拒否します。

+0

* foo()は明示的なパラメータを持たない関数を呼び出します*ここで 'foo()'とは何ですか?私はあまりあなたの質問が何であるかは分かりません。 –

+0

@YuvalItzchakovここにfooはありません。パラメータなしで関数 'foo'について話をしました。私は 'foo'メソッドが明示的なパラメータなしで定義されていれば、' foo() 'メソッドを呼び出すと言っています。 – user3663882

+0

'foo'がかっこなしで宣言されていなければ、コンパイルされません。'Some1'は明示的なパラメータを必要としません。' Some2'は明示的なパラメータを必要としません。あなたに何が混乱しているのかよくわからないのですか? –

答えて

2

f()は、空のパラメータリスト(および場合によってはこのリストの後の暗黙のパラメータ)を含むメソッドを呼び出します。 doSome1doSome2も空のパラメータリストを持たないので、もちろんitc.doSome1()itc.doSome2()はコンパイルされません。 itc.doSomeは、パラメータリストのない関数を呼び出すためコンパイルされ、暗黙のパラメータが挿入されます。スコープ内にimplicit Unitがないため、itc.doSome2はコンパイルされません。

itc.doSome3()では、()は、Unitの値であり、メソッド呼び出しのカッコではありません。実際にはitc.doSome3(())です。コンパイラは、このことについて警告を与える必要があります:

Warning:(15, 13) Adaptation of argument list by inserting() has been deprecated: this is unlikely to be what you want. 
     signature: ImplicitTypeConstraint.doSome3(u: Unit)(implicit ev: <:<[T,Int]): Unit 
    given arguments: <none> 
after adaptation: ImplicitTypeConstraint.doSome3((): Unit) 
itc.doSome3();// 
     ^
+0

しかし、空のパラメータリストを持つ関数と、パラメータを持たない関数との区別はどうしてですか?それには理由がありましたか? – user3663882

+2

空のパラメータリストはメソッドに副作用があることを示し、パラメータを使用しないメソッド(たとえば、フィールド/遅延ゲッタなど)ではパラメータが使用されないという慣習があります。 –

+0

@AlexeyRomanov:私はいくつかのタイプミスがあると思います。おそらく、あなたはいくつかの場所でdoSomeの代わりにdoSome1を意味しました。 doSomeメソッドはありません。 – Samar

1

私は暗黙のスコープでIntとみなすことができるタイプが必要である、ポイントがあると思います。そして、両方の

class ImplicitTypeConstraint[+T](val t : T) { 
    def doSome1()(implicit ev: T <:< Int) = println("Int value = " + ev(t)) 
    def doSome2(implicit ev: T <:< Int, u : Unit) = println("Int value = " + ev(t)) 
    def doSome3(u : Unit)(implicit ev: T <:< Int) = println("Int value = " + ev(t)) 
} 

を::

itc.doSome1 //compiles fine 
itc.doSome1() // compiles fine too 

しかしdoSome2

を呼び出すためにあなたは

implicit val intView = implicitly[Int <:< Int]

として
val itc = new ImplicitTypeConstraint(10) 
itc.doSome1 

そして、次のようにあなたがdoSome1を定義することができ、自分自身を提供することができます

itc.doSome2()     //compiles fine 
itc.doSome2(intView, println) // implicit won't work here 

doSome3を呼び出します。これは、メソッドのimplicitsを使用する通常の/正しい方法です。あなたはそれが好きなのはcurryです。

itc.doSome3(println) // compiles fine 
関連する問題