Skip to content

Swift_struct

kobayashiharuto edited this page Aug 1, 2021 · 7 revisions

構造体

実はオブジェクトじゃない。データを扱うための存在。


構造体とは?

C言語でも出てきましたね。あれです。
ただ、Swift の構造体はメソッドも書けます。イニシャライザも書けます。
クラスと全く一緒に見えます。つーかほとんど一緒です。

struct User {
    // プロパティ
    var name: String
    var age: Int

    //イニシャライザ
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
	
    // メソッド
    func greet() {
        print("こんにちは。私は\(self.name)です。\(self.age)才です。")
    }
}

let user = User(name: "小林", age: 20)
user.greet() // こんにちは。私は小林です。20才です。

クラスとの違い

一緒過ぎて、クラスとの違いを話すほうが楽です。


クラスは値の参照先を渡す

例えば以下のような、名前のプロパティを持つ Person クラスと、Person をプロパティとして持つ House クラスを用意します。

class Person {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

class House {
    var person: Person
    
    init(person: Person) {
        self.person = person
    }
    
    func call() {
        print("\(self.person.name)の家へようこそ")
    }
}

これを、以下のように使ってみましょう

let person = Person(name: "小林")
let kobayashiHouse = House(person: person)
kobayashiHouse.call() // 小林の家へようこそ

問題なさそうですね。しかしこうするとおかしなことになります。

let person = Person(name: "小林")
let kobayashiHouse = House(person: person)
kobayashiHouse.call() // 小林の家へようこそ

person.name = "佐藤"
kobayashiHouse.call() // 佐藤の家へようこそ

なんと、後から person の値を変更すると House に渡した person の値も変更されてしまいました。
つまりクラスは、値を渡しているのではなく、値の参照先 を渡しているということです。
同じところに参照しているので、一つを変えると全部変わってしまいます。


構造体は値をコピーして渡す

さて、Person クラスを構造体にしてみましょう。

struct Person {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

class House {
    var person: Person
    
    init(person: Person) {
        self.person = person
    }
    
    func call() {
        print("\(self.person.name)の家へようこそ")
    }
}

同じように使ってみても、値が変更されないことがわかります。

let person = Person(name: "小林")
let kobayashiHouse = House(person: person)
kobayashiHouse.call() 	// 小林の家へようこそ

person.name = "佐藤"
kobayashiHouse.call() 	// 小林の家へようこそ
print(person.name)		// 佐藤

もちろん、person の name プロパティは変わっていますが、クラスに渡した name プロパティは変わっていません。
これは構造体が渡されるとき、値がコピーされるからということになります。
もっと言えば、構造体が渡されるときは、写真を撮るようにその状態が渡されるというわけです。
その後どういじくられても写真のデータは変わらないように、構造体で渡したデータは変わることがありません。


継承できない

構造体は継承ができません。プロトコルは使えます。


使い道

とにかく、データが変わらなくて嬉しいことから、データを扱うクラスの場合は構造体で書いたりすることがよくあります。
まあ、あまり気し過ぎる必要はありません。とりあえず構造体ってのがあって、クラスっぽいよってことがわかっていれば今は OK です。
これはのちに 破壊的メソッドと非破壊的メソッド、そして immutable で詳しく話します。


まとめ

  • クラスとほぼ一緒、だけど値がコピーされるから渡された後に変わることがない
  • その性質を活かして、データを扱うクラスを構造体で書くことがある
  • 今はクラスとの使い分けで悩まないで良い。とりあえずクラス使っとけ。

Clone this wiki locally