くま's Tech系Blog

基本的には技術で学んだことを書き留めようと思います。雑談もやるかもね!

Swiftのvar、letについての個人的疑問を解消する

今回はSwiftのvar、letについてです。

たまにvar、letを定義したときに思わぬワーニングが表示されることがあり、個人的に疑問に思う場面があったので疑問を解消する記事にしようと思います

基本的なvar、letの解説は割愛しますが、varは変数でletは定数です。なので、letで初期値を定義すると後から値を変更しようとするとエラーが発生します

また、下記クラスを使うことを前提として進めます

class Test {
    var name: String?
    var tall: Int?
}

疑問点①

まずはクラスをインスタンス化して変数を変えるのにクラスをletで定義するべきというワーニングが発生するという点です

少しわかりにくいと思うので、下記にコードを載せます

// letに変えるべきというワーニングが発生!!
var test = Test()
test.name = "テスト"

個人的感覚かもしれませんが、値を変更するのでvarにするのではと思ってしまいます

これは、letが正しいです。なぜなら、初期化中にtestインスタンスへのポインタが割り当てられ、別の値が割り当てられることはなく定数扱いだからです

すべてのクラスインスタンスが実際にヒープ領域でバックアップされたクラスへのポインターなのです

Testクラスのnameが変わっても割り当てられたポインタが変わらないのでテストインスタンスがnullからnullではない値に変わったりする場合には変数扱いになるかもしれないです

疑問点②

2つ目の疑問は下記コードを見てください

let tests = [Test]()

let test = Test()
test.name = "テスト"
 
// varに変更しないとエラーが発生
tests.append(test)

testsは定数だからletでいい気がするのですが、appendする場合にはvarに変更しないとエラーになります

これはドキュメントに記載がありました

If you create an array, a set, or a dictionary, and assign it to a variable, the collection that’s created will be mutable. This means that you can change (or mutate) the collection after it’s created by adding, removing, or changing items in the collection. If you assign an array, a set, or a dictionary to a constant, that collection is immutable, and its size and contents can’t be changed.

どういうことかというとimmutable(不変)の配列やDictionaryなどはサイズや中身を変更できないのでletで定義しているとappendできないことになります。appendする場合にはvarに変更する必要がありそうです

疑問点を調べてみて

まだまだ学ぶことが多くあるなあと感じました。あと、ワーニングやエラーが発生してボタンを押すと勝手にFixする場合があると思います。そのときに自動で修正されて終わりではなく、どういう原因だったのかなど深掘りしたほうが理解が深まりそうです

参照

www.web-dev-qa-db-ja.com

docs.swift.org