SwiftのOptionalをC++のnullptrやstd::optionalと比べて整理する
Swiftの String? は、C++のポインタや std::optional を知っていると理解しやすいです。
ただし、nullptr とは少し違います。
公式では、optionalは値があるか、まったく値がないかを扱うものとして説明されています。
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Optionals
Optionalは値があるかないか
var name: String? = "Makonote"
name = nil
String? は「Stringかnil」です。
String とは別の型です。
let a: String = "A"
let b: String? = "B"
b はそのまま String として使えません。
C++のstd::optionalに近い
C++で近いのは std::optional<T> です。
std::optional<std::string> name = "Makonote";
name = std::nullopt;
Swiftの String? も、「あるかもしれない値」です。
ポインタのnullというより、値の有無を型で表していると見る方が自然です。
if letで取り出す
Optionalの中身を安全に取り出すには if let を使います。
let name: String? = "Makonote"
if let name {
print(name)
}
中の name は String です。
C++ならこういうチェックに近いです。
if (name) {
std::cout << *name;
}
guard letで早く抜ける
関数の先頭で値がない場合に抜けたいなら guard let が便利です。
func greet(_ name: String?) {
guard let name else {
return
}
print("Hello, \(name)")
}
Swiftでは、この形がかなりよく出ます。
ネストが浅くなるので、if let より読みやすいことがあります。
!はなるべく避ける
! を使うと強制的に取り出せます。
let name: String? = nil
print(name!)
これは実行時に落ちます。
C++でいう、nullかもしれないポインタをそのままdereferenceする感覚に近いです。
std::string* name = nullptr;
std::cout << *name;
どうしても「ここでは絶対にnilではない」と言える場所だけに絞った方がいいです。
まとめ
SwiftのOptionalは、C++の nullptr より std::optional に近いです。
T?は「Tがあるかもしれない」TとT?は別の型if letで安全に取り出す- 早く抜けるなら
guard let !はクラッシュの可能性がある
Optionalを雑に外すより、nilの場合にどうするかを先に決めて書く方がSwiftでは読みやすいです。


