今回は 強参照循環
を打開するための手段として在る 弱参照
と 無所有参照
のそれぞれの特徴についてを眺めていきます。Swift に触れていると何かと出てくるものたちですので、この機にそれぞれの特徴を窺いながらその周辺視野に映るものにも意識を向けて見ていけたらいいなと思っています。よろしくお願いしますね。
———————————————————————————————————— 熊谷さんのやさしい Swift 勉強会 #227
00:00 開始 01:13 弱参照と無所有参照のおさらい 02:40 弱参照とは 03:53 弱参照はインスタンス解放をブロックしない 04:28 弱参照の宣言方法 04:55 弱参照している値が解放されると nil になる 05:46 NULL 安全との相乗効果 09:21 弱参照は必ず変数で扱う 10:23 変数という言葉に覚える違和感 12:02 何を以ってプロパティーとするか 13:37 変数自体がアクセサーを持てる 16:27 ローカル変数でも didSet が使える 18:56 ローカル変数における didSet の使い道も探していきたい 20:52 reduce に見る変数の活用場面 22:35 定数とラベル付けの感覚 23:13 変数を使わずにコードを書くのは良い練習 23:44 クロージングと次回の展望 ————————————————————————————————————
Transcription & Summarize : 熊谷さんのやさしい Swift 勉強会 #227
続きを見ていきますが、弱参照(Weak Reference)についてもう少し詳しく説明します。弱参照とは、インスタンスを参照するときにそれを強く保持しない参照のことです。これだけ聞いても意味が分かりにくいかもしれませんが、詳細は過去の勉強会でお話ししたので、そちらも参考にしてくださいね。
弱参照を利用することによって、循環参照を防ぐことができます。循環参照が発生すると、ガベージコレクターが不要なメモリを解放できなくなり、メモリリークが発生してしまいます。これを防ぐために、適切に弱参照を使うことが大事です。例えば、デリゲート(delegate)パターンを使用する際に、メモリリークを防ぐために弱参照を使います。
例:
class Parent {
var child: Child?
}
class Child {
weak var parent: Parent?
}
上記の例のように、Child
クラスの parent
プロパティを弱参照 (weak
) として宣言しています。これにより、Parent
と Child
が互いに強く参照し合わないようにし、循環参照を防ぐことができます。
次に、所有参照(Strong Reference)と無所有参照(Unowned Reference)についても触れておきます。無所有参照とは、所有権を持たない参照のことです。無所有参照は弱参照と似ていますが、弱参照と異なり、オプショナルではなく、参照先が確実に存在することが保証される場合に使います。
例:
class Customer {
var card: CreditCard?
}
class CreditCard {
unowned let customer: Customer
init(customer: Customer) {
self.customer = customer
}
}
この例では、CreditCard
クラスの customer
プロパティを無所有参照 (unowned
) として宣言しています。ここで、Card
は必ず Customer
に関連付けられているため、オプショナルではない無所有参照を使用しています。
これらの参照方法は、そのインスタンスの寿命や関係性に応じて使い分ける必要があります。理解するためには何度も練習が必要ですが、コード例を実際に書いてみると身につきやすいと思います。
何か分からないことがあれば、気軽に質問してくださいね。勉強会は繰り返し確認できる良い機会ですので、一緒に頑張りましょう。 それでは、飛んでいきます。まずは、自動リファレンスカウンティング(ARC)についてです。ARCは、参照されたインスタンスを破棄することを厳密に管理します。要するに、参照が残っている限りはARCがそのインスタンスを存続させますが、弱参照についてはARCがインスタンスを解放するという流れに持っていきます。
プロパティや変数の宣言の前にweak
を置くことで、弱参照にすることができます。弱参照は参照するインスタンスを強く保持しないため、それを参照している状態でも解放することが可能です。これが弱参照の大きな特徴ですね。したがって、弱参照が参照しているインスタンスが解放された時の対処を考えなければなりませんが、ARCが自動的にマネジメントしてくれるのがありがたいところです。
弱参照について特筆すべきなのは、ARCが自動でセットしてくれるおかげで、解放済みになっても安心できることです。これはヌル安全(null safety)が言語仕様に組み込まれているからです。ヌル安全がない言語では、ヌルアクセスの例外が発生する可能性があります。例えば、他の言語で弱参照がヌルになったらヌル例外が発生する可能性もあります。
しかしSwiftでは、弱参照はオプショナル型で扱うのが原則ですので、コンパイラが強制的にヌルチェックを入れます。これにより、解放されたかどうかの確認が必須となり、コードがしっかりと書かれていれば、ARCが適切にマネジメントしてくれます。このようにして、言語仕様がヌル安全を提供することで非常に良い効果が得られるわけです。
ここで少し話が変わりますが、おととい日立さんの勉強会に参加しました。そこで、「リターンではヌルを返さない」という話があり、議論が盛り上がりました。その本はヌル安全の言語ではなかったのですが、ヌル安全があるからこそヌルを返す話になり、非常に面白いと感じました。
ヌル安全があると全く違う世界観になります。言語の仕様や思想の違いによってセオリーも変わってきます。例えば、ある文化圏では特定のパターンが良しとされるのも、その言語仕様や思想によるものです。このような視点で考えると、なぜその文化圏ではそのようなことが良しとされるのか、面白い見方ができると思います。この話をしていて本当に面白いと感じました。 うん、まあその観点のうちのどこに当たるかというのは、弱参照とヌル安全によって、ARC(Automatic Reference Counting)によってですね、なかなか素晴らしい効果を発揮しています。次に、弱参照はその値を実行時にヌルに変えられる必要があるため、必ず定数ではなく変数として宣言しなければなりません。そしてオプショナル型となるのも大きな特徴です。まあ、これは必然的にこの形を取るわけですが、これによって得られるものが交差するのか、まあまあ定然な形であるので、どちらからでもいいのですけど、そのあたりもね、弱参照を使用する上で理解しておきたい特徴の一つですね。
ここで脱線しますが、弱参照についてはこれだけ理解していただければと思います。この内容を掴めた方がいたらぜひ教えてくださいね。とても大事なので。ただ、それはさておき、プロパティや変数という言葉を聞くたびに、言語仕様が面白いなと思います。これはこの勉強会でも何回も話してきたことですが、紹介したくなる時がありまして、プロパティや変数、このツイートを見ていると、定数と変数、見方に違いがあるのが面白いです。
プロパティという言葉を一般的なものとするならば、プロパティにも定数と変数があります。レッドで宣言したプロパティとバーで宣言したプロパティがあるわけです。そのときにバーとレッドって変数や定数じゃないですか。その段階で変数という言葉が出てくるのが微妙な感じがします。まあ、日本語全体の問題かもしれませんが。
プロパティや変数、そして定数や変数について考えると、イミュータブルかミュータブルかといった感覚になります。同じような感覚ですが、Javaではフィールドという言葉が、C++ではメンバー変数という言葉が、Objective-Cではインスタンス変数という言葉があります。これらは純粋な値を保存するだけのストレージです。対してプロパティは、ゲッターやセッターでパクセル化し、オーバーライドを可能にするなどの効果を持つ、ちょっと特別な存在です。
仮にプロパティ的な意味で言っているとしたら、普通の型に所属していない変数でもゲッターセッターを持てる点が興味深いです。オブジェクトがあって、値を持たせ、ゲッターとして何かを返す、あるいは書き込みをした後に機能を追加することができるというわけです。
ローカル変数にもゲッターセッターを持たせると、たとえば以下のようなコードが書けます。
private var value: Int {
get {
return newValue
}
set {
value = newValue
}
}
この書き方が面白いのは、実際のコードではあまり使われないものの、プログラマが介入できる余地があることです。純粋な属性とは違って、ゲッターセッターがあるおかげで複雑な処理を後付けで追加することができるわけです。
これをプロパティと呼べるかどうかは人それぞれですが、私はプロパティと呼べるだろうと考えています。この発想は、プログラマの知識や経験によって左右されるので、ぜひ学んで実践してみてほしいです。ローカル変数でのゲッターセッターの使い方が見えてくると、新しい発想が広がるので面白いですね。
具体的な場面としては、他の方法でうまく活用したり、チェーンしたりという使い方が浮かびます。リデュースやリファレンスのように、局所的な変数の制約をうまく活用することで、コードのパフォーマンス向上や最適化が図れるわけです。
実際にコードを書く際には、レッド縛りでコードを書いてみると、マップやリデュースの使い方が上手くなるというのも一つの手です。こうすることで、バー変数を使わずに済む場面が増え、Swiftに慣れていくことができます。 そのやり方はおすすめですね。さて、時間になりましたので、今日はこれぐらいにしておきましょう。
略参照に関しては、ざっと概要を把握できたと思います。次回からは、もう少しこの略参照や関連する具体的な使い方について掘り下げていこうと思います。
それでは、今日はこれで終わりにしましょう。お疲れ様でした。ありがとうございました。