[Swift] Optional 型についてのまとめ Ver2

# はじめに

* [以前の記事](http://qiita.com/cotrpepe/items/e30c7442733b93adf46a)は一部内容が古くなったので、全面的に書き直しました


# 環境

* Xcode 6.1 GM seed 2
* iOS Simulator (iPhone6 / iOS 8.1)


# Optional 型とは？

* Optional 型 - `nil` の代入を許す
* 非 optional 型 - `nil` の代入を許さない


# Optional 型の宣言方法

* `Int` 型

```swift
var a: Int? // Optional 型
var b: Int  // 非 optional 型
```

* `String` 型

```swift
var a: String? // Optional 型
var b: String  // 非 optional 型
```

# `T?` は `Optional<T>` のシンタックスシュガーである

```swift
var a: Int?
var b: Optional<Int> // Int?　と同じ意味
```


# `Optional<T>` は `enum` 型である

`Optional<T>` は、標準ライブラリの中で　`enum` 型として定義されている。

```swift
enum Optional<T> : Reflectable, NilLiteralConvertible {
    case None    // nil に相当する
    case Some(T) // T 型（素の型）の値が入る（Int 型や String 型の値など）
    ...
}
```

# Optional 型は `nil` が代入されるのを許す

```swift
var a: Int? // Optional 型
a = nil     // -> OK
```

非 optional 型に `nil` を代入しようとすると、コンパイラエラーが発生する。

```swift
var b: Int // 非 optional 型
b = nil    // -> Compiler error: Type 'Int' does not conform to protocol 'NilLiteralConvertible'
```

# Optional 型の初期値は `nil`

```swift
var a: Int? // Optional 型
println(a)  // -> nil
```

非 Optional 型の場合、初期値には何も入っていない（nilも入っていない）。

```swift
var b: Int // 非 optional 型
println(b) // -> Compiler erorr: Variable 'b' used before being initialized
```

# Optional 型は、非 Optional 型と同じようには扱えない

```swift
var a: Int = 1
println(a + 2) // -> 3
```

```swift
var b: Int? = 1
println(b + 2) // -> Compiler error: Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?
```
上記のとおり、`Int?` 型は、`Int` 型とは別の型なので、同じように操作することはできない。`Int` 型と同じように操作するためには、変数を「アンラップ」する必要がある（後述）。


# ラップ（wrap）とアンラップ（unwrap）

## 「ラップされている」とは？

Optional 型（`Optional<T>` 型）の変数のことを「ラップされている」と言う（おそらく、`Optional<T>`型に `T` 型の変数が「包まれている」ことに由来すると思われる）。

## 「アンラップする」とは？

Optional 型（`Optional<T>` 型）から `T` 型の変数を取り出すことを、「アンラップする」と言う。


# Optional 型をアンラップする方法

Optional 型の変数をアンラップする方法として、以下のものがある。

1. Forced unwrapping
2. Optional chaining
3. Optional binding
4. 比較演算子


# 1. Forced Unwrapping

ここでは、以下の Dog クラスを例に説明を進める。

```swift
class Dog {
    func bark() -> String {
        return "Wan!"
    }
}
        
var wrappedDog: Dog? = Dog() // Optional 型
        
//
// アンラップをしないと、bark() メソッドを呼び出すことができない
//
println(wrappedDog.bark()) // -> Compiler error: 'Dog?' does not have a member named 'bark'
```

「!」 を optional 型の変数の後ろに付けるとアンラップすることができる。これを Forced unwrapping と言う。

```swift
//
// Forced unwrapping
//
println(wrappedDog!.bark()) // -> Wan!
```

Forced unwrapping で`nil` をアンラップしようとすると、ランタイムエラーが発生する。

```swift
wrappedDog = nil
println(wrappedDog!.bark()) // -> Runtime error: unexpectedly found nil while unwrapping an Optional value
```


# 2. Optional Chaining

「?」 を使ってアンラップすることを optional Chaining と言う。

```swift
//
// Optional Chaining
//
println(wrappedDog?.bark()) // -> Optional("Wan!")
```

Optional chaining で `nil` をアンラップしようとすると、`nil` が返ってくる。

```swift
wrappedDog = nil
println(wrappedDog?.bark()) // -> nil
```

# 注意： Optional Chaining は Optional 型を返す

Forced unwrapping はアンラップをした後に、最終的な戻り値をそのまま返す。以下の場合、bark メソッドの戻り値（String 型）をそのまま返す。

```swift
//
// Forced unwrapping
//
println(wrappedDog!.bark()) // -> Wan!
```

Optional chaining はアンラップをした後に、最終的な戻り値を optional 型にラップしてから返す。以下の場合、bark メソッドの戻り値（String 型）を optional 型にラップしてから返す。

```swift
//
// Optional chaining
//
println(wrappedDog?.bark()) // -> Optional("Wan!")
```
上記の命令では以下の処理が行われている。

1. `wrappedDog` をアンラップする 
2. `bark()` メソッドを呼ぶ
3. `bark()` メソッドが `String` 型を返す
4. `String` 型を optional 型にラップする
5. `Optional<String>` 型を返す

## Optional Chaining が Optional 型を返す理由

これは、optional chaining が `nil` を返す可能性があるためである。アンラップ対象の変数が `nil` だった場合、optional chaining はランタイムエラーを起こさずに `nil` を返す。`nil` を許容するためには、戻り値は optional 型でなければならない。

# 注意：「?」には二つの別の意味がある

以下は「optional 型の宣言」という意味である。

```swift
var a: Int? // Optional 型
```

一方で、以下は「optional chaining」を意味する。

```swift
//
// Optional chaining
//
println(wrappedDog?.bark()) // -> Optional("Wan!")
```

どちらも「?」を使っているが、意味が異なるので混同しないように注意。


# 3. Optional Binding

`if` や `while` 文の条件式で宣言され、optional 型の変数を代入された変数は、非 optional 型になる。これを「optional binding」と言う

```swift
var wrappedDog: Dog? = Dog() // Optional 型

//
// Optional binding
//
if var unwrappedDog = wrappedDog { // unwrappedDog はアンラップされた値（素の Dog 型）になる

    //
    // unwrappedDog は非 optional 型なので、アンラップは不要
    //
    println(unwrappedDog.bark()) // -> Wan!
}
```

`let` も使用可能。

```swift
if let unwrappedDog = wrappedDog {
    println(unwrappedDog.bark()) // -> Wan!
}
```

`while` 文でも使用可能。

```swift
while var unwrappedDog = wrappedDog {
    println(unwrappedDog.bark()) // -> Wan!
    break
}
```

`wrappedDog` が `nil` だった場合、条件式は `false` になる。

```swift
wrappedDog = nil
if var unwrappedDog = wrappedDog { // false
    println("This is not printed out.")
}
```

# 4. 比較演算子

比較演算子を使うと、optional 型の変数が自動的にアンラップされる。

```swift
var wrappedInt: Int? = 1 // Optional 型
        
//
// 自動的にアンラップされる
//
println(wrappedInt == 1) // -> true
println(wrappedInt >= 1) // -> true
println(wrappedInt >  1) // -> false
println(wrappedInt <= 1) // -> true
println(wrappedInt <  1) // -> false
println(wrappedInt != 1) // -> false
```

Optional 型の変数を比較演算子の右に置いてもかまわない。

```swift
println(1 == wrappedInt) // -> true
```

Optional 型の変数が `nil` であっても、エラーは発生しない。

```swift
wrappedInt = nil
println(wrappedInt == 1) // -> false
```


## 注意： `nil` は負の無限大より小さい

`nil` は、負の無限大より小さい。

```swift
println(nil < -Double.infinity) // -> true
```

これが奇妙な結果を招くことがあるので注意。

```swift
var wrappedDouble: Double? = nil
        
if wrappedDouble < 0.0 {
    println("\(wrappedDouble) is a negative number.") // -> nil is a negative number.
}
```


# Implicitly Unwrapped Optional 型とは？

「Implicitly unwrapped optional 型」 とは、「自動的にアンラップされる optional 型」のことである。


# Implicitly Unwrapped Optional 型の宣言方法

* `Int` 型

```swift
//
// 「?」ではなく、「!」を使う
//
var a: Int! // Implicitly unwrapped optional 型
var b: Int? // Optional 型
```

* `String` 型

```swift
var a: String! // Implicitly unwrapped optional 型
var b: String? // Optional 型
```

# `T!` は、`ImplicitlyUnwrappedOptional<T>` のシンタックスシュガーである

```swift
var a: Int!
var b: ImplicitlyUnwrappedOptional<Int> // Int! と同じ意味
```


# `ImplicitlyUnwrappedOptional<T>` は `enum` 型である

`ImplicitlyUnwrappedOptional<T>` は標準ライブラリの中で `enum` 型として定義されている。

```swift
enum ImplicitlyUnwrappedOptional<T> : Reflectable, NilLiteralConvertible {
    case None    // nil に相当する
    case Some(T) // T 型（素の型）の値が入る（Int 型や String 型の値など）
    ...
}
```


# Implicitly Unwrapped Optional 型の初期値は `nil`

```swift
var a: Int! // Implicitly unwrapped optional 型
println(a)  // -> nil
```

# Implicitly Unwrapped Optional 型は自動的にアンラップされる

```swift
var iwrappedDog: Dog! = Dog() // Implicitly unwrapped optional 型
        
//
// 「!」や「?」を付けなくても、自動的にアンラップされる
//
println(iwrappedDog.bark()) // -> Wan!
```

`nil` をアンラップしようとすると、ランタイムエラーが発生する。

```swift
iwrappedDog = nil
println(iwrappedDog.bark()) // -> Runtime error: unexpectedly found nil while unwrapping an Optional value
```

# 注意： 「!」には二つの別の意味がある

以下は「Implicitly unwrapped optional 型の宣言」という意味である。

```swift
var a: Int! // Implicitly unwrapped optional 型
```

一方で、以下は「Forced unwrapping」を意味する。

```swift
var wrappedDog: Dog? = Dog() // Optional 型

//
// Forced unwrapping
//
println(wrappedDog!.bark()) // -> Wan!
```

どちらも「!」を使うが、意味が異なるので混同しないように注意。


# Optional 型の代入演算子

以下の変数をもとに説明を進める。

```swift
var wrapped: Int?  = 1 // Optional 型
var iwrapped: Int! = 2 // Implicitly unwrapped optional 型
var unwrapped: Int = 3 // 非 optional 型
```

## Optional 型の代入

Optional 型は、implicitly unwrapped optional 型に代入できる。

```swift
iwrapped = wrapped // OK
```

Optional 型は、非 optional 型に**「代入できない」**。

```swift
unwrapped = wrapped // Compiler error: Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?
```

Forced unwrapping でアンラップされた optional 型は、非 optional 型に代入できる。

```swift
unwrapped = wrapped! // OK
```

Optional chaining でアンラップされた optional 型は、非 optional 型に**「代入できない」**（optional chaining の戻り値が optional 型であるため）。

```swift
unwrapped = wrapped? // Compiler error: Value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?
```

## Implicitly Unwrapped Optional 型の代入

Implicitly unwrapped optional 型は、optional 型に代入できる。

```swift
wrapped = iwrapped // OK
```

Implicitly unwrapped optional 型は、 非 optional 型に代入できる（暗黙的にアンラップされていることに注意）。

```swift
unwrapped = iwrapped // OK
```

## 非 Optional 型の代入

非 optional 型は、optional 型に代入できる。

```swift
wrapped = unwrapped // OK
```

非 optional 型は、implicitly unwrapped optional 型に代入できる。

```swift
iwrapped = unwrapped // OK
```


# ?? 演算子

`a ?? b` は、以下の処理を行う。

その１） a が `nil` でなければ、`a!`（a をアンラップしたもの） を返す。

```swift:aがnilでない場合
var a: Int? = 1

//
// a は nil でないので、a をアンラップしたものを返す
//
println(a ?? 2) // -> 1
```

その２） a が `nil` であれば、b を返す。

```swift:aがnilの場合
a = nil

//
// a は nil なので、2 を返す
//
println(a ?? 2) // -> 2
```


## `a ?? b` は、`a != nil ? a! : b`のシンタックスシュガーである

以下の２つは同じ意味である。

```swift
var a: Int? = 1

println(a ?? 2) // -> 1
```

```swift
println(a != nil ? a! : 2) // -> 1
```


# まとめ

## Optional 型と Implicitly Unwrapped Optional 型

|型                              |宣言方法                         |型の実体（`enum` 型） |アンラップ操作は必要か？|
|:------------------------------|:-------------------------------|:-----------------|:-------------------|
|Optional 型                     |`var a: T?`                   |`Optional<T>`       |必要                |
|Implicitly unwrapped optional 型|`var a: T!`|`ImplicitlyUnwrappedOptional<T>`       |不要（自動的にアンラップされる）|


## `nil` をアンラップしようとしたときの挙動

|型                              |アンラップの方法                        |`nil` をアンラップしたときの結果|
|:------------------------------|:-------------------------------------|:--------------------------|
|Optional 型                     |Forced unwrapping (e.g. `wrappedDog!`)|ランタイムエラー              |
|Optional 型                     |Optional chaining (e.g. `wrappedDog?`)|`nil` を返す                |
|Implicitly unwrapped optional 型|自動的にアンラップされる                  |ランタイムエラー              |

## アンラップ時の戻り値

|型         |アンラップの方法                 |戻り値             |例|
|:----------|:-------------------------------|:--------------|:----|
|Optional 型|Forced Unwrapping               |最終的な戻り値をそのまま返す|`wrappedDog!.bark() // -> String 型`|
|Optional 型|Optional Chaining               |最終的な戻り値を optional 型にラップしてから返す|`wrappedDog?.bark() // -> Optional<String> 型`|
|Implicitly Unwrapped Optional 型|自動的にアンラップされる|最終的な戻り値をそのまま返す|`iwrappedDog.bark() //-> String 型`|


# 参考文献

[The Swift Programming Language](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/index.html#//apple_ref/doc/uid/TP40014097-CH3-XID_0)

[Facets of Swift, Part 1: Optionals](https://medium.com/@tammofreese/facets-of-swift-part-1-optionals-b8ba5b0051a2)

[stakoverflow - What does an exclamation mark mean in the Swift language?](http://stackoverflow.com/questions/24018327/what-does-an-exclamation-mark-mean-in-the-swift-language)

[先取り！Swift](http://dev.classmethod.jp/smartphone/iphone/forestalling-swift/)

[Wikipedia - Swift (プログラミング言語)](http://ja.wikipedia.org/wiki/Swift_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E))

[Swiftのnilがなるほどわからん](http://qiita.com/inamiy/items/b186e9612352b31261df)

[Swiftの`nil`は`-∞`よりも小さい ？？](http://qiita.com/satoshia/items/ed6fe951503538d2f56b)

[Swiftの比較演算子を使うとき，変数は自動でアンラップされる。](http://qiita.com/satoshia/items/6ee7952c3438e234c4db)

[【Swift入門】Optional型 (?, !) をまとめてみた](http://ntech.hatenadiary.com/entry/2014/07/10/135444)

[[Swift][Optional] アンラップしているはずなのに、アンラップされない](http://qiita.com/cotrpepe/items/3958a6863f1e412073e1)

[@dankogai さんと @_shingt さんの tweet](https://twitter.com/dankogai/status/523420219872526336)