【Swift】構造体(struct)とは?クラスとの違いと使い方

この記事からわかること
- Swiftの構造体とは?
- 構造体の使い方
- イニシャライザの実装方法
- Memberwise Initializerとは?
- 値型と参照型
- クラスと構造体の違い
index
[open]
\ アプリをリリースしました /
Swiftの構造体の使い方についてまとめていきます。
構造体(struct)とは
Swiftには構造体と呼ばれるクラスと似たような構造、性質を持つデータ構造があります。
使い道はデータを決まった形式で保持するために使います。
基本的にはクラスと同じような扱いをすることができ、変数や関数を定義したり、インスタンス化する要領で変数に格納したりすることも可能です。
これもクラスと同様ですが構造体の中に定義した変数はプロパティ、関数はメソッドと呼ばれます。動作は一緒ですが呼び方が異なるので注意してください。
使い方と定義方法
クラス(class
)と同じような形式で、構造体はstruct
で定義します。
構造体の中には定数、変数、イニシャライザ、関数が定義可能です。
おすすめ記事:【Swift】プロパティの種類!ストアドプロパティやタイププロパティとは?
構造体名はPascal記法(UpperCamelCase記法)、プロパティやメソッドはlowerCamelCase記法を用いることが推奨されています。
記法 | 説明 | 例 |
---|---|---|
CamelCase記法 | 先頭は小文字で単語ごとに大文字 | $myData |
アンダースコア記法 | 小文字で単語の間をアンダースコア(_)で繋ぐ | $my_data |
Pascal記法 | 先頭と単語の区切りが大文字 | $MyData |
構造体型のデータを作成する
実際に定義した構造体に準じたデータを作成してみます。Xcodeでは構造体を定義すると入力補完が効いてくれるので構造体名を入力するだけで必要なプロパティを表示してくれます。

定義した構造体に倣ったデータを扱うには変数の中に格納します。生徒の各教科の点数を保持させるStudent構造体
を定義してみます。
インスタンス化してプロパティにアクセス
構造体を変数に格納するとプロパティやメソッドにはドットシンタックスを使ってアクセスできるようになります。変数に格納することをクラス同様にインスタンス化と呼びます。
プロパティの初期値
構造体を定義する際に初期値を与えることも可能です。初期値を与えることでインスタンス化時に、値を渡すことを省略することができます。
一方クラスではそもそも初期値を与えないとエラーになってしまいます。構造体では初期値を記述しなくてもエラーにはならないのでこれがクラスと構造体の違いの1つになります。
この理由は後述してありますのでそちらをご覧ください。
初期値を与える
初期値を与えた場合は型を指定しなくても格納された値に基づいた型を自動で定義してくれます。これを型推論と呼びます。
プロパティの種類による初期値
プロパティにはストアドプロパティ(stored property)とコンピューテッドプロパティ(computed property)の2種類があります。ストアドプロパティは値を保持し、コンピューテッドプロパティは計算式を保持し、結果を返します。
イニシャライザを使用する場合プロパティ全てに値を格納しないといけませんがコンピューテッドプロパティは値を格納する必要はありません。
構造体のプロパティをメソッドから変更する
構造体に定義しているメソッドからプロパティの値を変化させようとするとエラーが発生してしまいます。
エラーを発生させるコード
これを防ぐにはメソッドの前にmutating
をつけます。
mutatingで解決したコード
Swift UIを使用する場合では@State
をつけることで解決することができます。両者の違いについては下記記事を参考にしてください。
イニシャライザ(init)
構造体には初期化を行うために作成時に自動実行される処理イニシャライザ(init)を実装することができます。イニシャライザの中では構造体で定義したプロパティにself.プロパティ名
でアクセスできます。引数には各プロパティ名と型を列挙して構造体のプロパティに明示的に入れ込みます(初期化)。
イニシャライザには定義しているプロパティ全てに何かしらの初期値を与えないと以下のようなエラーになってしまいます。なのでインスタンス化時の引数としてを入れ込んでいないself.sumScore
には自力で値を格納しないといけません。
Memberwise Initilaizer
クラスは初期値の指定が必須でしたが構造体では指定しなくてもエラーになりません。
これは構造体のみに実装されている「Memberwise Initializer」と呼ばれるイニシャライザによるものです。
Structure types automatically receive a memberwise initializer if they don’t define any of their own custom initializers.
リファレンスを見てみると上記のように明記されています。要約すると「構造体は、独自のイニシャライザを定義していない場合、メンバー(プロパティ)ごとの初期値を自動的に受け取る」ということになります。
Memberwise Initializerにより暗黙的に実装されている
初期値を指定しない場合はインスタンス化時の引数で値を指定しないと以下のようなエラーになります。
クラスと構造体の違い
クラスとの違いとポイント
- 構造体は継承ができない
- デイニシャライザ(デストラクタ)が使えない
- 値渡し
両者の大きな違いはclassは参照型で構造体は値型であるところです。変数や引数などで操作した際に参照型はオリジナルのデータの格納場所が渡されるが、値型は複製された値が渡されます。
この挙動はインスタンス変数の値を変更すると分かりやすいです。
値型
その時時点のデータをそのままコピーするだけなので、元のインスタンスとはリンクしていない
参照型
データが格納されているメモリの参照を渡すだけなので、「s」も「sA」も読みにいく場所は同一になるので変更が影響し合う
構造体にプロトコルを準拠させる
構造体にはプロトコルを指定することもできます。指定した場合はその構造体にはプロトコルに乗っ取ったプロパティやメソッドの定義が義務付けられます。
プロトコルに準じた構造体ではない場合は以下のようなエラーが発生します。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。