👽

【Swift UI】struct(構造体)をわかっている気になっているピヨピヨエンジニアへ

2024/01/05に公開

structについて解説していく!

structについて完全に熟知した気になっていたが、アプリ開発中に分からなくなってきたので学び直す!

structとは

クラスに近い性質を持つデータをカプセル化し保存する機能でして、
カプセル化と言うのは、容易に外部や内部から変更できないようにする仕組みです。

書き方

struct 構造体名 {
  コード
}

classに近いと書きましたが、違いは以下などです。

1.structは、継承できない
2.structは、デイニシャライザできない
3.structは、値渡し型
4.structは、イニシャライザが必要ない

structの特徴

継承できない&値渡し

この二つは詳しく書くつもりはありません!
継承できないとは、そのままです! 
classは他のクラスやプロトコルを継承して、継承元の変数(プロパティ)や関数(メゾット)にアクセスできます。
しかし、struckはクラスはもちろんとして他のstructを継承できません。

値渡しとは、ざっくり説明するとstrcutの変数に値を渡すときや、struckから他のstructや変数に値を渡すときに、コピーして値を渡すと言うことです。
クラスは参照渡しです。

具体的には、

structAのnameにkidoと入っていて、structBのnameにstructAのnameを代入したとする。
この時に、structBのnameにkidoが入る。仮にAとBがクラスであってもここまでは同じです。
しかし、structBのnameをsatoにすると、structAのnameはkidostructBのnameはsatoになります。これが値渡し
もしAとBがクラスならAもsatoになっています。これが参照渡し

デイニシャライザできない

structはdeinitできない!
デイニシャライザとは、インスタンスを破棄しメモリを解放するときに使う特殊メゾットです。
基本的には、デイニシャライザできるクラスでもARCがあるので、明示的に呼び出すことはあまりない。

イニシャライザが必要ない

イニシャライザが必要ないです。
もちろん、イニシャライザすることもできますし、あらかじめプロパティに初期値を与えることもできます。

プロパティに初期値を渡しておく

struct Person{
    var name: String = "ore"
    var age: Int = 23
}

あらかじめプロパティに初期値を与えるとインスタンス化の時に、初期値を与えなくて済みます。
また、特定のプロパティにだけインスタンス時に初期値を与えることもできます。

    let person = Person()
    let person1 = Person(name: "aitu",age: 12)
    let person2 = Person(name: "omae")

ちなみに、初期値を与えないと

struct Person{
    var name: String
    var age: Int
}

下記画像のように、インスタンス化時に初期化が十分でないとエラーになります。
真ん中は、nameとageに初期値を与えているためエラーは起きない。

カプセル化 structの値を変える。

カプセル化しているので、変数に初期値を入れてしまえば変えることはできません。
しかし、初期化した後でも変える方法はあります。

mutating

mutatingを使うことで、値を変えることができるようになります。
使わないと下記画像のようにエラーになります。
画像1

画像2

画像1は、ageプロパティと同じstruct型のPersonからageをの値を増やそうとしてエラーが出ています。
画像2は、Supermanと言う外部のstructからPersonのageを増やそうとしてエラーが出ています。

メゾット(関数)にmutatingをつけると〜〜〜

エラーが消えました!

このようにageを変えられました!!

コード 見た目

上記画像のようにswiftUIで表示させるために、increaseAge()を書き換えました。

struct Person {
    var name: String
    var age: Int
    
    mutating func increaseAge() -> Int {
        var incrasedAge = age + 2
        return incrasedAge
    }
}

結論

mutatingを関数につけるとstruct内のプロパティを変えられる。

structにプロトコルを準拠させる。

structはプロトコルのみ継承できます!

protocol human {
    var name: String { get set }
    var age: Int { get set }
    mutating func increaseAge() -> Int
}

struct Person: human {
    var name: String
    var age: Int
    
    mutating func increaseAge() -> Int {
        let incrasedAge = age + 2
        return incrasedAge
    }
}

このように、プロトコルは継承できます。しかし、完全にプロパティもメゾットもプロトコルと同じにしなければいけません。

Discussion