LoginSignup
7
7

More than 3 years have passed since last update.

【Swift】クロージャのキャプチャって?パート2

Last updated at Posted at 2021-03-18

はじめに

パート1の続きです。

ネスト関数とクロージャ

前回の例題をネスト関数で置き換えました。結果は全く同じです。

func maker(_ a: Int, _ b: Int) -> (() -> Int) {
    var localvar = 0
    func localfunc() -> Int {
        globalCount += 1 // globalCountは参照されるだけ
        localvar += b // localvar, bがキャプチャされる
        return localvar
    }
    return localfunc
}

メソッドとイニシャライザ

通常の関数と同様に、クラスなどのメソッド、イニシャライザもクロージャとして扱うことかできます。

class Friend {
    let name: String
    init(name: String) {
        self.name = name
    }
    deinit {
        print("deinit", name)
    }
    func sayName() {
        print("私は\(name)です。")
    }
    func sayHello(to f: Friend) {
        print("こんにちは、\(f.name)さん\(name)です。")
    }
}

次のように実行してみます。

let clo1: (String) -> Friend = Friend.init
var clo2: (Friend) -> ()
do {
    let fr1 = clo1("花子")
    clo2 = fr1.sayHello(to:)
    fr1.sayName()
}
let fr2 = Friend(name: "太郎")
clo2(fr2)
clo2 = fr2.sayHello
}

出力結果は以下のようになります。

私は花子です
こんにちは太郎さん花子です
deinit 花子

まず、イニシャライザを定数clo1に代入し、これを使ってdo文のなかでインスタンスが生成できていることがわかります。次に変数clo2にクラスのインスタンスメソッドを代入していますが、do文から出ることによって定数fr1自体は消滅します。その後、clo2に引数を与えるとちゃんと実行できていることからdo文のなかで生成したインスタンスはまだ生存していることがわかります。変数clo2に別の値を代入するとこのインスタンスは解放されます。

キャプチャリスト

ここまで、クロージャはその周辺のローカル変数をキャプチャして共有できることを説明してきました。一方、クロージャが元の変数と必ずしも値を共有しなくてもよい場合もあります。そのような場合、クロージャのインスタンスを生成する際に変数のコピーを作り、クロージャないでそのコピーの値を使うことができます。

var a, b, c: () -> ()
do {
    var count = 0
    var name = "Objective-C"
    a = { []            in print("A: \(count), \(name)") }
    b = { [count]       in print("B: \(count), \(name)") }
    c = { [name, count] in print("C: \(count), \(name)") }
    count = 1
    name = "Swift"
}
a()
b()
c()

先頭に変数名を[]で囲んだものがつけられています。これをキャプチャリストといいます。この中に書き並べられた変数はクロージャの生成時にコピーが作成され、そのあとは元の変数の値に変更があっても影響されません。
出力結果は以下のようになります。

A: 1, Swift
B: 0, Swift
C: 0, Objective-C

おわりに

クロージャのキャプチャの説明は以上です。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7