if文とnil

オプショナルバインド
nilでないことを保証する「!」

オプショナルバインド

オプショナルな変数においては、次のような条件文にすることで「値を持っていれば実行する」といったようなことをif文でやることができる。
「定数か変数 = オプショナルな変数」であればよいので、別にletやnameでなくていい。

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
	//optionalNameがnilを指す場合これは実行されない(この場合else文の方にまわされる)
	greeting = "Hello, \(name)"
} 

nilでないことを保証する「!」

toInt()はInt型のものかnilを返すため、次のconvertedNumberはオプショナルな型Int?になる。

let possibleNumber = "123"
let convertedNumber = possibleNumber.toInt()

でもって、この後こんな処理をすることを考えてみる。先程のオプショナルバインドと違ってif文の条件にあるのはInt?型のconvertedNumber単品である。

if convertedNumber {
	println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
	println("\(possibleNumber) could not be converted to an integer")
}

toInt()という関数の結果がIntかnilか保証されないからこそconvertedNumberはInt?型なわけだが、このif convertedNumber ~のif文の中のconvertedNumberは確実にInt型の値を持っていることが保証される。何故ならif convertedNumberを通過して2行目を実行するためにはconvertedNumberがInt型の値を持っていないといけないから。
見ての通り2行目のconvertedNumberはただの変数ではなくおしりに「!」がついている。これは、「オプショナルな変数だがこの時点でnilを指さないことが確実」であることを示す印である。

上のオプショナルバインドで紹介したやり方だと「!」はいらない。

if let actualNumber = possibleNumber.toInt() {
	println("\(possibleNumber) has an integer value of \(actualNumber)")
}

え、その理由?
It has already been initialized with the value contained within the optional, and so there is no need to use the ! suffix to access its value.
(・∀・;)
超意訳すると、オプショナルなpossibleNumber.toInt()をもとに新たに生まれたactualNumberのお陰で!がいらないってこと、かな?w

つーわけで、if文の処理の結果からnilでないことが明らか……というのが上の話であるが、これ以外にも「最初にnil以外の値を与えた直後」もnil出ないことは明らかである。
以下のように「オプショナルだがちゃんとした値で初期化したため(その時点では)nilでないことが明らか」なやつをimplicitly unwrapped opitionalsという。誰かいい日本語を与えてほしい。とにかく、コイツの場合は変数宣言・初期化時に「?」ではなく「!」を使う

//普通にオプショナルな変数を宣言・初期化
let possibleString: String? = "An optional string."
//初期化直後でnilでないことが明らかなので!を付けてprintln
//An optional string.
println(possibleString!)

//implicitly unwrapped optionalsなヤツの初期化、?ではなく!をつける
let assumedString: String! = "An implicitly unwrapped optional string."
//nilでないと保証されている形式のオプショナルな変数なので!はいらない
//An implicitly unwrapped optional string.
println(assumedString)
if assumedString {
	println(assumedString)
}
if let definiteString = assumedString {
	println(definiteString)
}

駄目だ、この辺訳が怪しい。間違ってたらだめぽよだ。
でも、nilになりそうな時にはimplicitly unwrapped optionalsを使うべきでないとは書いてある。nilであるかどうかのチェックが必要なら普通のオプショナル使えってさ。
※implicitly unwrapped optionalsな変数にはnilを代入可能

↑ PAGE TOP