クロージャとは
クロージャとはスコープ内の変数や定数を保持した再利用可能なひとまとまりの処理のこと。
関数がクロージャの一種であることから、クロージャと関数は共通する点が多い。
定義方法
関数はfuncキーワードによる定義が必要だが、クロージャはクロージャ式という定義方法で定義する。
{ (引数名1: 型, 引数名2: 型...) -> 戻り値の型 in
処理
...
return 戻り値
}
実行方法
クロージャの呼び出し方は、クロージャが代入されている変数や定数の末尾に()をつけて呼び出す。
// 定義したクロージャを定数に代入
let sumFunction = { (x: Int, y: Int) -> Int in
return x + y
}
// クロージャを代入した定数名の末尾に()をつけて呼び出す
let result = sumFunction(1, 2) // 3
クロージャの特徴
変数と定数のキャプチャ
クロージャはクロージャ自身が定義されたスコープ内の変数や定数への参照を保持するキャプチャ機能がある。通常ローカルスコープで定義された変数や定数はローカルスコープ内でしか使用することはできないが、クロージャはキャプチャ機能により、ローカルスコープ外でクロージャが実行されても変数や定数を利用することができる。
let double: (Int) -> Int
do {
let two = 2
double = { num in
return num * two
}
}
// ローカルスコープ外でクロージャgreetingを実行しても
// ローカル変数symbolを利用することができる
double(3) // 6
また、クロージャによるキャプチャの対象は、変数や定数に格納されている値ではなく、その変数や定数自身をキャプチャしている。そのため、キャプチャしている変数や定数の値の変更はクロージャ実行時に反映される。
let exponentialGrowth: () -> Int
do {
var count = 1
exponentialGrowth = {
count *= 2
return count
}
}
exponentialGrowth() // count == 2
// 前回実行時の変数countへの変更が反映されている
exponentialGrowth() // count == 4
exponentialGrowth() // count == 8