#構造体とは?
構造体とは値型の一種で、ストアドプロパティの組み合わせによって1つの値を表すことができるものの事を言います。
簡単に言うと、これは継承不可のクラスのようなものであり以下のような特徴を持っています。
・複数の値を一個の構造体で管理できる(ストアドプロパティの組み合わせによって一つの値を表す)
・辞書とは違い、同じ構造のオブジェクトを複数生成可能
・クラスと違い参照不可
・クラスは参照型に対し、構造体は値型
・イニシャライザも関数も使用可能
このような構造体の用途は多くあり、例えば画面上の幅と高さは2つのプロパティをもつ構造体で表すことができ、統一して管理したい複数のプロパティを使用する際に便利です。
#定義方法
下記のように定義は非常にシンプルで、structの後に構造体名を記述、そして{}の中にプロパティなどを定義すればOKです。
struct 構造体名 {
構造体の定義
}
サンプルコード
実装コード例は以下のようになります。
初期値なしのストアドプロパティに対してイニシャライザで、引数からの値を与え、実行時に値を返すようなプログラムになっています。
//構造体定義
struct Article {
//ストアドプロパティ定義(初期値なし)
let id: Int
let title: String
let body: String
//initを使用することでイニシャライザ定義
init(id: Int, title: String, body: String) {
self.id = id
self.title = title
self.body = body
}
func printBody() {
print(body)
}
}
//インスタンス化時に引数に値を置くことで、イニシャライザで初期値を与える
let article = Article(id: 1, title: "title", body: "body")
article.printBody()
//実行結果
body
##インスタンス化時の定数への注意
以下のコードを見ると、最初のインスタンス化(初期化)時には変数に構造体を代入し、コンパイル成功。2回目の時は定数に構造体を代入し、コンパイルエラーが発生しています。つまり以下の例のように、インスタンス化時に定数に代入した場合、それ以降値の変更はできなくなるので注意してください。
struct SomeStruct {
var id: Int
init(id: Int) {
self.id = id
}
}
var variable = SomeStruct(id: 1)
//コンパイル成功
variable.id = 2
let constant = SomeStruct(id: 1)
//コンパイルエラー
constant.id = 2
##メソッド内でのストアドプロパティの変更
構造体内で定義したメソッド内でストアドプロパティの値を変更する場合、mutatingの使用が必要になります。
以下のコードのようにイニシャライザで引数を参照して代入する時は必要ありませんが、メソッドで代入する時はmutatingの記述が必要で、もし記述がなくメソッドだけの場合はコンパイルエラーになるので注意してください。
struct SomeStruct {
var id: Int
init(id: Int) {
self.id = id
}
mutating func someMethod() {
id = 4
}
}
var a = SomeStruct(id: 1)
a.someMethod()
a.id
//実行結果
4
##メンバーワイズイニシャライザ
メンバーワイズイニシャライザとは構造体にデフォルトで用意されているイニシャライザのことです。
構造体では独自にイニシャライザと定義しない場合、このメンバーワイズイニシャライザが自動的に定義され型が持っている各ストアドプロパティと同名の引数を割り当ててくれます。
そのため以下のコードのように、コメントアウトされているイニシャライザが記述しなくても暗黙的に初期化を行ってくれます。
struct Article{
let id: Int
let title: String
let body: String
//以下のイニシャライザが自動的に定義されている
//init(id: Int, title: String, body: String) {
// self.id = id
// self.title = title
// self.body = body
//}
}
let article = Article(id: 1, title: "Hello", body: "...")
article.id
article.title
article.body
//実行結果
1
Hello
...