ア | イ | ウ | エ | オ |
カ | キ | ク | ケ | コ |
サ | シ | ス | セ | ソ |
タ | チ | ツ | テ | ト |
ナ | ニ | ヌ | ネ | ノ |
ハ | ヒ | フ | ヘ | ホ |
マ | ミ | ム | メ | モ |
ヤ | ユ | ヨ | ||
ラ | リ | ル | レ | ロ |
ワ | ヰ | ヴ | ヱ | ヲ |
ン |
A | B | C | D | E |
F | G | H | I | J |
K | L | M | N | O |
P | Q | R | S | T |
U | V | W | X | Y |
Z | 数字 | 記号 |
サブルーチンへのリファレンス(ポインター)と、そのプライベートなデータをセットにしたもの。日本語では閉包と呼ぶらしい。
通常の関数であれば、関数内で定義された変数は関数終了時点で破棄される。
しかし関数オブジェクトを変数に代入するとなると事情が変わってくる。この時はその代入された変数が有効である間は保持されるため、その間はクロージャーを複数回呼び出した時には前回の値が継続して使用される。
上述の説明をKotlinを使って説明する。例えば、次のようなクロージャーを定義する。
fun increment(): ()->Int { var num = 0 return { ++num } }
この関数自体は引数を持たないが、内部にもつ変数をインクリメントしながら返すラムダ式を返す。
これを実際に使ってみる。
fun main() { val closure = increment() println(closure()) println(closure()) println(closure()) }
これは次のような結果を返す。
1 2 3
同じことをクロージャーを使わないで書くことも一応はできる。
fun main() { var num = 0 val increment = { ++num } println(closure()) println(closure()) println(closure()) }
この場合、numは関数内のどこからでもアクセスできてしまう。ここで「変数の名前衝突」という問題が発生しうることと、意図しない変更が生じうるという問題がある。特定目的の変数はできるだけカプセル化(隠蔽化)されるのが望ましい。
そこで必要な処理をクロージャーというまとまりで定義することで、こういった問題を解決することができる。
コメントなどを投稿するフォームは、日本語対応時のみ表示されます