[Swift 基本の型 第4回(第2部)] Optional型
Swiftの基本の型 第4回 第2部になります。前回のOptional型の続きです。頑張りましょう!
本記事は「Swift実践入門」を参考にしています。
Optional型のケースについて
SwiftではOptionalはenumという列挙型を用いて定義されています。
列挙型は、複数の識別子をまとめる型で、それぞれの識別子をケースといいます。
Optional型では、.none
と.some
のケースがあり、enumでは列挙されたケースのうち、どれかを一つを値として持つため、.none
か.some
を値として持ちます。
・.none
値が存在しないことを表すケースになります。
値が存在しないことを表すケース.none
はOptional\nil
と表記できます。
・.some
値が存在することを表すケース.some
はOptional\Optional(値)
と表記可能です。
以上をまとめると次の表のようになります。
ケース | .none | .some |
---|---|---|
値 | 不在 | 存在 |
簡略化表記 | nil | Optional(値) |
また、列挙型のケースとしてOptional型の.some
の値を生成する場合、Int型やString型は.some
に持たせる値から型推論が可能です。
型推論を利用すると、.some
の生成は\
let some = Optional.some(1) // Optional<Int>型
一方で.none
を生成する場合は型推論のもととなる値が存在しないため、そのままでは\
let none: Int? = Optional.none // Optional<Int>型
上記の例のように.some
の生成では値から型推論ができる一方で、.none
の生成では型を明示する必要があります。
オプショナルチェイン
前回はアンラップの方法について3つの方法を用いて、Optional型の値を取り出す方法を確認しましたが、 今回はオプショナルチェインというアンラップを伴わずに値のプロパティやメソッドにアクセスする方法について確認します。
オプショナルチェインを用いずに、Optional\
復習になりますが、次の例1ではOptional\
例1 ) オプショナルバインディング
let optionalDouble = Optional(1.0) // 1 let optionalIsInFinite: Bool? if let double = optionalDouble { optionalIsInFinite = double.isInfinite } else { optionalIsInFinite = nil } print(String(describing: optionalIsInFinite))
例2 ) オプショナルチェイン
let optionalDouble2 = Optional(1.0) // Optional(1.0) let optionalIsInFinite2 = optionalDouble2?.isInfinite print(String(describing: optionalIsInFinite2))
例1と例2を比較してもらえばわかる通り、オプショナルチェインを用いた場合だとコードが少なくてすみますね!
例のようにオプショナルチェインを用いれば、アンラップを伴わずにWrapped型のプロパティやメソッドにアクセスできます。オプショナルチェインを利用するには、Optional\
オプショナルチェインでは、Optional\
map(_:)メソッドとflatMap(_:)メソッド
map(_:)メソッドとflatMap(_:)メソッドは、アンラップを伴わずに値の変換を行うメソッドです。 map(_:)メソッドの引数には、値を変換するクロージャを渡します。
※クロージャとは、波カッコ {} のブロックで囲んだ中にある処理を実行する自己完結型の機能のことです。関数と似ていますね。メリットとしては関数のようにいちいち名前をつけなくても良いという点になります。
map(_:)メソッドでは、Wrapped型の値が存在すればクロージャを実行して値を変換し、値が存在しなければ何も行わないという処理になります。 次の例では、Int?型の定数に対して値を2倍にするクロージャを実行し、結果としてInt?型のOptional(34)を受け取っています。
let d = Optional(10) let e = d.map({ value in value * 2 }) // 20 type(of:e) // Optional<Int>.Type
また、map(_:)メソッドを用いて、別の型に変換することもできます。 次の例では、Int?型の定数に対してString型に変換するクロージャを実行し、結果としてString?型の値Optional(17)を受けとっています。
let f = Optional(10) let g = f.map({ value in String(value) }) // "10" type(of:g) // Optional<String>.Type
flatMap(_:)メソッドもmap(_:)型と同様に値を変換するクロージャを引数にとりますが、クロージャの戻り値はOptional\
例1 ) flatmapメソッド
let h = Optional("10") let i = h.flatmap({ value in Int(value) }) // 10 type(of:i) // Optional<Int>.Type
例2 ) mapメソッド
let j = Optional("10") let k = j.map({ value in Int(value) }) // 10 type(of:k) // Optional<Optional<Int>>.Type
上記の例では、String?型の定数に対してInt?型に変換するクロージャを実行し、Int?型の値Optional(17)を受けとっています。
もし、ここでflatMap(_:)メソッドではなくmap(_:)メソッドを使用してしまうと、最終的な結果は二重にOptional\
暗黙的アンラップされたOptional\型
暗黙的アンラップは、 次のような書き方で定義します。
var A: Int! A = 1
ここで、定義した際の初期値はnilになります。
この定義によって生成されたOptional\
暗黙的アンラップされたOptional\
let p: Int! = 1 p + 1 // Int型と同様に演算が可能 var q: Int! = nil q + 1 //値が入っていないため実行時エラー
Optional\
終わりに
今回、Swift 基本の型 第4回第2部としてOptional型のうち、オプショナルチェインとmapメソッドについてまとめました。他にも暗黙的アンラップについてもまとめましたので、アプリを作っていく上でわからなくなった際は第4回を読み直して再度理解を深めましょう!