web-dev-qa-db-ja.com

'it'を使用したGroovyネストクロージャ

クロージャー内のコードは、it変数を参照できます。

8.times { println it }

または

def mywith(Closure closure) {
   closure()
}

mywith { println it }

この動作を念頭に置いて、次のコードが0011を出力することは期待できません。

2.times {
   println it 

   mywith {
      println it
   }
}

そして代わりに私は書かなければなりません

2.times { i ->
   println i 

   mywith {
      println i
   }
}

私の質問は、パラメータのないクロージャがit変数を必要としない場合でもオーバーライドする理由です。

20
Mykola Golubyev

それはGroovyの 正式なクロージャー定義 と関係があると思います:

クロージャには1 ... N個の引数があり、静的に型付けされている場合と型付けされていない場合があります。最初のパラメーターは、明示的な引数が指定されていない場合、その名前が付けられた暗黙的な型なし引数を介して使用できます。呼び出し元が引数を指定しない場合、最初のパラメーター(ひいてはそれ)はnullになります。

つまり、Groovy Closureには、it(特に指定されていない場合)およびと呼ばれる少なくとも1つの引数が常にあります。 itは、パラメーターとして指定されていない場合はnullになります。

2番目の例では、代わりに囲んでいるクロージャのスコープを使用します。

15
Daff

このようにクロージャを定義すると

def closure = {println "i am a closure"}

パラメータがないように見えますが、実際にはitという名前の暗黙的なパラメータが1つあります。これは次の方法で確認されます。

def closure = {println "i am a closure with arg $it"}
closure("foo")

印刷する

「私はargfooのクロージャです」

0個のパラメーターを受け取るクロージャーを本当に定義したい場合は、次を使用します。

def closure = {-> println "i am a closure"}

したがって、例は次のように書き直すことができます。

2.times {
   println it 

   mywith {->
      println it
   }
}
22
Dónal