The Swift Programming Language - Initialization（初期化）をまとめる


[The Swift Programming Language をまとめるトップ](http://qiita.com/kiyotaman/items/052f82e9f93590b79c64)

## Initialization（初期化）
クラス、構造体、列挙型でインスタンスを生成するときに行う処理
Swift のイニシャライザーの特徴は値を return しない

### Setting Initial Values for Stored Properties（保存型プロパティの初期値を設定）
保持型プロパティの値は初期化中に必ず値を定義しないといけない

#### Initializers（初期化）
init() が一番簡単な記述の方法

temperature　は保持型プロパティなので、 init() 内で値を指定しないとエラーになる

```swift
struct Fahrenheit {
    var temperature: Double
    init() {
        temperature = 32.0
    }
}
var f = Fahrenheit()
println("気温の初期値 \(f.temperature)°")
// prints "気温の初期値 32.0°"
```

#### Default Property Values（プロパティーの初期値）
プロパティーを宣言するときに初期値を設定することもできる

```swift
struct Fahrenheit {
    var temperature = 32.0
}
```

> **NOTE**
初期値を指定する時はイニシャライザー init() で定義するよりプロパティーの宣言のところでやったほうが後々良い場合がる

### Customizing Initialization（初期化のカスタマイズ）
#### Initialization Parameters（初期化の引数）
イニシャライザーを定義するときに引数を設定することができる
関数やメソッドを定義するのとほぼ同じルール

```swift
struct Celsius {
    var temperatureInCelsius: Double = 0.0
    init(fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
// boilingPointOfWater.temperatureInCelsius は 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius は 0.0
```

外側のパラメータとローカルのパラーメータを指定してそれぞれ値を受けてインスタンスを生成している
それぞれのインスタンスのプロパティの値は上記の通り

#### Local and External Parameter Names（ローカルと外側パラメータの名）
関数やメソッドとほぼ同じ動き
ただ、```()```の前に名前はつけない init のみ
外側の引数を指定しない場合自動的にローカル名と同じ名前が付けられる

```swift
struct Color {
    let red = 0.0, green = 0.0, blue = 0.0
    init(red: Double, green: Double, blue: Double) {
        self.red   = red
        self.green = green
        self.blue  = blue
    }
}
// 以下のように名前を指定して定義する
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)

// 以下は名前を指定していないので、コンパイルタイムエラーになる
// let veryGreen = Color(0.0, 1.0, 0.0)
```

#### Optional Property Types（オプショナルプロパティタイプ）
**!**　がついたオプショナル型のプロパティは初期化の時に自動で nil が代入されるので、初期化の時に明示的に値を代入する必要はない

```swift
class SurveyQuestion {
    var text: String
    var response: String?
    init(text: String) {
        self.text = text
    }
    func ask() {
        println(text)
    }
}
let cheeseQuestion = SurveyQuestion(text: "チーズは好きですか?")
cheeseQuestion.ask()
// prints "チーズは好きですか？"
cheeseQuestion.response = "はい、好きです。"
```

このように、response はオプショナル型なので初期化の時に明示的に値を指定していない
"no string yet" の状態ということになる

#### Modifying Constant Properties During Initialization（初期化時の定数の更新）
初期化中に定数（let）の値を定義することができる
サブクラスからはできない


```swift
class SurveyQuestion {
    let text: String
    var response: String?
    init(text: String) {
        self.text = text
    }
    func ask() {
        println(text)
    }
}
let cheeseQuestion = SurveyQuestion(text: "ビーツはどうですか？")
cheeseQuestion.ask()
// prints "ビーツはどうですか？"
cheeseQuestion.response = "はい、好きです。"
```

初期化の時に定数の値を引数で渡し定義することができる

### Default Initializers（標準イニシャライザー）
構造体と何も継承していないプロパティ初期値が全て設定されているベースクラスは、以下の様に init() を省く事ができる 

```swift
class ShoppingListItem {
    var name: String?
    var quantity = 1
    var purchased = false
}
var item = ShoppingListItem()
```

name はオプショナルなので nil がセットされ、 quantity は　1 、 purchased は false がセットされているので init() が省ける

#### Memberwise Initializers for Structure Types（構造体のメンバー変数初期化）
構造体を初期化する時の簡易的な方法で、初期化の時に構造体のメンバー変数の名前を添えてインスタンスを生成することができる

```swift
struct Size {
    var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)
```
Size(...) でインスタンスを生成するときに、 _init(width:height:)_ が自動で呼ばれている

### Initializer Delegation for Value Types（値型のイニシャライザーデリゲーション）
イニシャライザーの中でイニシャライザーを呼ぶ方法がイニシャライザーデリゲーションと言う

```swift
struct Size {
    var width = 0.0, height = 0.0
}
struct Point {
    var x = 0.0, y = 0.0
}
struct Rect {
    var origin = Point()
    var size = Size()
    init(origin: Point, size: Size) {
        self.origin = origin
        self.size = size
    }
    init(center: Point, size: Size) {
        let originX = center.x - (size.width / 2)
        let originY = center.y - (size.height / 2)
        self.init(origin: Point(x: originX, y: originY), size: size)
    }
}
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
    size: Size(width: 3.0, height: 3.0))
// centerRect の originは (2.5, 2.5) そのサイズは (3.0, 3.0)
```

init(center: Point, size: Size)内で self.init を使って別のイニシャライザーを呼び出している

### Class Inheritance and Initialization（クラスの継承と初期化）
スパークラスを継承しているクラスの保存型プロパティは初期値を保持しないといけない

#### Designated Initializers and Convenience Initializers（必須と補足的なイニシャライザー）
Designated Initializer は必ず呼ばれるイニシャライザーで、二番目の選択肢として Convenience Initializer がある
詳細は [オリジナルのドキュメントのサンプルを眺めるとなんとなく分かる](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-XID_284)
[convenience な init メソッド](http://qiita.com/takkyun/items/afde067c08bc046ffe53#2-8) にも解説あり

#### Syntax for Designated and Convenience Initializers（書式）
以下のように convenience を init の前に付ける

```swift
convenience init(parameters) {
    statements
}
```

### Setting a Default Property Value with a Closure or Function（クロージャーや関数のプロパティ初期値の設定）
クロージャーや関数を初期値としてプロパティに指定する事ができる
クロージャーや関数が定義されたクラスのインスタンスを生成するたびに呼ばれる

こちらも分かりやすい[クロージャを使ったプロパティの初期値](http://qiita.com/takkyun/items/afde067c08bc046ffe53#2-3)

```swift
class SomeClass {
    let someProperty: SomeType = {
        //このクロージャーの中に someProperty の初期値をつくる
        // someValue の 型は SomeType と同じである必要がある
        return someValue
        }()
}
```