1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Optional型について備忘録

Posted at

唐突にSwiftを使うことになり、Optional型と初めて遭遇したのでその走り書きをまとめてみました。
解釈が間違っているところ、不足しているところなどありましたらコメント頂けますと幸いです。

Optional<Wrapped>型とは

Swift は nil(JavaでいうところのNull)を許容しない。
しかし nil を使いたい場面はある。そんなときに Optional型(データ型の1つ) を使う。
Optional<Wrapped><Wrapped>はジェネリクス

// nilを許容しない
var s: String = "hello world"   // "hello world"
s = nil                         // error
// ?を型につける→下記のコードの省略形
var s: String? = "hello world"  // "hello world"    ※
s = nil                         // nil
// ※のString?と全く同じ処理
var s: Optional<String> = "hello world" 

アンラップ(値の取り出し)

Optional型の変数はそのままでは通常の変数としては扱えない。

Optional型の値を通常の値に変換する アンラップ という方法が必要となる。

そもそもOptional(値)とはどのような状態でしょうか。
Optionalは値を包み込むラップ(包み紙)のイメージです。オプショナル型は値をOptionalというラップ1枚で包み込んでいます。
すると、たとえ中身がない(=nil)状態でも包み紙だけは存在するため、とりあえず扱うことができます。
オプショナル型の値がnilでも使えるのは、この包み紙が存在しているためです。
しかし、この便利な包み紙があるために値はラッピングされ、直接扱うことができません。扱うためにはラップを取り除き、中身の値を取り出さなくてはいけません。
この包み紙を取り除き、値を取り出すことをアンラップと言います。

オプショナルバインディング(if-let文による値の取り出し)

Optional<Wrapped>型の値の有無に応じて処理を切り替えて値を取り出す処理

let year: Int? = Int("2020")        
if let y = year {                   // yというOptional型に値が存在した場合に処理をする
    print("あと\(y - 2016)年")
} else {
    print("エラー")
}

?? 演算子

Optional<Wrapped>型に値が存在しない場合のデフォルト値を指定する時に使う演算子

let optionalInt: Int? = 1
let int = optionalInt ?? 3
//結果は1

let optionalInt: Int? = nil
let int = optionalInt ?? 3
//結果は3

左辺のOptional<Wrapped>型に値が存在すれば左辺の値を、
存在しなければ右辺の値を返す

強制アンラップ

!演算子によってOptional<Wrapped>型から値を取り出す方法

let x: Int? = 1
let y: Int? = 1
x! + y!
//結果は2

Optional<Wrapped>型に値が存在しなければ実行時エラーとなるリスクがある
だから使い所としては以下の状況以外では避けるべき

- 値の存在が明らかな箇所
- 値が存在しないならばプログラムを終了したい箇所

オプショナルチェイン

アンラップを伴わずに値のプロパティやメソッドにアクセスする記法

let optionalDouble = Optional(1.0)

// **********オプショナルバインディングを使用時********
let optionalIsInfinite: Bool?
if let double = optionalDouble {
    optionalIsInfinite = double.isInfinite
} else {
    optionalIsInfinite = nil
}
// *****************************************

// ----------オプショナルチェインを使用時-------------
let optionalIsInfinite = optionalDouble?.isInfinite
// ----------------------------------------------

print(String(describing: optionalIsInfinite))
//結果は同じ;false

Optional<Wrapped>型の変数や定数がnilだった場合は?以降に記述されたプロパティやメソッドへアクセスは行われずにnilが返される

暗黙的なアンラップ

変数の宣言時に!をつける
アンラップせずにアクセスできる

var number: Int!
number = 10
print(number) //強制的にアンラップ
// 10

まとめ

?!の違いはアンラップを強制的に行うかどうか
どちらも同じOptional型である
特に!は使い所をしっかり確認しなければ実行時エラーとなる

参考

どこよりも分かりやすいSwiftの"?"と"!"
https://qiita.com/maiki055/items/b24378a3707bd35a31a8#optional%E5%80%A4
SwiftのOptional(オプショナル)が少しややこしいのでまとめてみた
https://qiita.com/ToraDady/items/6079b9f07bebece672eb

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?