Swift さくっと確認したい基礎文法 [Struct(構造体)]


# Struct[構造体]とは？

ひとことで簡単に言えば、継承のできないクラス。

* 複数の値を１個のオブジェクトで管理できる。
* 辞書とは違い、同じ構造のオブジェクトを複製することができる。
* クラスとは違い、継承はできない。
* クラスが参照型であるのに対して構造体は値型
* イニシャライズも関数も使える。

# 使いどころ
汎用的に使いたいので、クラス化したい！
ただ、継承は必要ない。
というときに使う。

と理解しているつもりですが、
間違っている等のご意見があれば優しくご指摘をお願いします。


# 基本的な書き方

基本的な書き方はクラスと同様。

```swift
struct 名前 {
	var hogehoge:型
	var hugahuga:型
	let weiwei:型
}
```

初期値なしでも、ありでも書くことができる。

インスタンスを作る際は
下記の`var iPhone5 = IPhone5()`ように基本的にはクラスと同様に書く。
※初期値がないStructの場合は、インスタンス作成時に初期値を設定する必要がある。


```swift

// 初期値なし
struct SmartPhone {
    var os:String
    var version:Double
    var width:Int
    var height:Int
}

// 初期値あり
struct IPhone5 {
    var os:String = "iOS"
    var version:Double = 7.0
    var width:Int = 320
    var hight:Int = 568
}

// 初期値なしの場合、インスタンス作成時に初期値を入れる。
var iPhone6 = SmartPhone(os: "iOS", version: 8.3, width: 375, height: 667)
println(iPhone6.width) // 375

// 初期値ありの場合、そのままインスタンス化
var iPhone5 = IPhone5()
println(iPhone5.width) // 320
```


# イニシャライザを定義する

Structでは、クラスと同様にイニシャライザを定義できます。
書き方は同じです。

下記の例では、widthとheightの合計値によって
sizeの初期値を決めています。

```swift
struct Box {
    let width:Int
    let height:Int
    let size:String
    
	
    init(width:Int, height:Int){
        self.width = width
        self.height = height
        
        var sumSize = width+height
        
        switch (sumSize) {
        case 0...100:
            size = "S"
        case 101...200:
            size = "M"
        case 201...300:
            size = "L"
        default:
            size = "Free"
        }
    }
}

// Bozをインスタンス化(initメソッドを呼ぶ)
var newBox = Box(width: 100, height: 30)
println(newBox.size) // M
```


# クラスが参照型であるのに対して構造体は値型ってどういうこと？

参照型であるクラスは
複数の変数に代入されても、一つのオブジェクトを共有しているので
いずれかの変数の値が変更されれば、他の変数にもそれが反映される。

一方で、
値型である構造体は、
複数の変数に代入された場合、新しい構造体として代入されるので、
いずれかの変数が変更されても他の変数にその変更は影響しない。

言葉で説明しても分かりづらいので、
下記の例を見れば理解できると思います。

```swift:swift

// 構造体(値型)
struct CardStruct {
    var color:String
}

// クラス(参照型)
class CardClass {
    var color:String
    
    init(color:String){
        self.color = color
    }
}

var cardStruct1 = CardStruct(color: "black")
var cardStruct2 = cardStruct1
cardStruct2.color = "red"
println("cardStruct1：\(cardStruct1.color)、cardStruct2：\(cardStruct2.color)")


var cardClass1 = CardClass(color: "black")
var cardClass2 = cardClass1
cardClass2.color = "red"
println("cardClass1：\(cardClass1.color)、cardClass2：\(cardClass2.color)")
```

```swift:出力
// 構造体：cardStruct2.colorを変更してもcardStruct1.colorはそのまま
"cardStruct1：black、cardStruct2：red"

// クラス：cardClass2.colorが変更されるとcardClass1.colorも変更される。
"cardClass1：red、cardClass2：red"
```

# 関数を定義する

こちらもクラスと同様に関数を定義できます。
インスタンスを作成した後、関数を呼び出します。

```swift:swift
struct Card {
    var width:Int
    var height:Int
    
    func getSquare() -> Int {
	
        return width*height
    }
}

var card = Card(width: 100, height: 150)
println(card.getSquare())
```

# Struct(構造体)のプロパティを変更する

構造体は基本的にはメソッド内で、
自分自身のプロパティの値を変更することはできません。
以下のコードはエラーになります。

```swift:swift
struct Card {
    var width:Int
    var height:Int
    
    func getSquare() -> Int {
		// エラー(メソッド内でプロパティを変更できない。)
        self.width = 300 
        return width*height
    }
}

var card = Card(width: 100, height: 150)
println(card.getSquare())
```

プロパティを変更する場合は、
変更するメソッドに`mutating`を付けます。

```swift:swift
struct Card {
    var width:Int
    var height:Int
    
    mutating func getSquare() -> Int {
        self.width = 300
        return width*height
    }
}

var card = Card(width: 100, height: 150)
println(card.getSquare())

```

※追加予定
structにおけるsubscriptついて