【Swift】guard文の使い方。条件に合わないときの処理を抜けるコードをシンプルに書く。(Swift 2.1、XCode 7.2)
guard文とは
guard文とは、条件式がfalseの場合の処理のみを記述する構文である。trueの場合の処理が無いif文と考えるとイメージしやすい。→「if文の記事」
以下のように記述する。
1 2 3 4 5 |
guard 条件式 else { 処理 return または break または throw } |
例えば、以下のコードは引数が9以下の場合に挨拶をする関数をguard文を使って実装した例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* ** guard文の使用例 */ //引数が9以下の場合に挨拶をする関数 func sayGoodMorning(time:Int) { guard ( time < 9 ) else { print("朝ではありません。") return } print("おはようございます。") } sayGoodMorning(10) //実行結果 //朝ではありません。 |
if文を使っても同じことができる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* ** if文の使用例 */ //引数が9以下の場合に挨拶をする関数 func sayGoodMorning(time:Int) { if ( time >= 9 ) { print("朝ではありません。") return } print("おはようございます。") } sayGoodMorning(10) //実行結果 //朝ではありません。 |
guard文は、条件に合わない場合に処理を抜けるコードをシンプルに記述するために用意された構文である。なので、elseブロックの中でreturn、break、throwのいずれかを必ず記述するルールになっている。
以下のコードはelseブロックでreturnまたはthrowを記述しなかったためにコンパイルエラーになった例。ちなみに、breakはループの中でしか書けない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* ** guard文のelseブロックの中でreturn、breakまたはthrowを記述しなければエラーになる。 */ //引数が9以下の場合に挨拶をする関数 func sayGoodMorning(time:Int) { guard ( time < 9 ) else { print("朝ではありません。") } print("おはようございます。") } sayGoodMorning(10) //コンパイルエラー //error: 'guard' body may not fall through, consider using 'return' or 'break' to exit the scope |
guard文の使いどころ
「if文で同じことが書けるならif文を使えばいいじゃないか。」と思うかも知れないのでguard文の使いどころについて説明しておく。
guard文は「処理継続条件→合わない→抜ける」をイメージしやすく、シンプルに書ける。それをif文でシンプルに記述しようとすると、「処理中断条件→合う→抜ける」というイメージの流れになり、条件に合っているのに抜けるという感覚がスムーズに頭に入ってこないことがある。
このように、guard文を使う利点は処理を抜けるためのコードを、シンプルでイメージしやすく記述できるところにある。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* ** guard文をシンプルに書く。 */ //引数が9以下の場合に挨拶をする関数 func sayGoodMorning(time:Int) { guard time < 9 else { return } print("おはようございます。") //後続処理は省略 } sayGoodMorning(10) |
オプショナルバインディングで利用する
オプショナルバインディングはif文でよく使われる機能で、条件式に「var 変数名 = オプショナル型変数」を記述し、変数がnilで無い場合はtrueの処理、nilの場合はfalseの処理が行われる機能である。→「オプショナルバインディング記事」
以下のコードはif文でオプショナルバインディングを利用する例。String型の文字列をInt型にキャストして5個の価格を表示するメソッドである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* ** if文でオプショナルバインディングをする例 */ //5個の価格を表示する関数 func printPrice(data:String) { if var price = Int(data) { print("5個で\(price * 5)です") } } //メソッド呼び出し printPrice("120") // 実行結果 // 5個で600です |
guard文でもオプショナルバインディングを利用できる。以下のコードは上記コードをguard文に変更したコード。
if文とguard文のオプショナルバインディングには大きく異なる仕様がある。それは、if文の場合はif-elseブロックを抜けると条件式で代入した変数は使えなくなるが、guard文ではelseブロックを抜けたあとでも変数を利用できる点である。
オプショナルバインディングで継続可能と判定されてそのまましばらく変数を使うときに、if文だと変数を使う場所をブロックで囲まなければならないが、guard文だとブロックは1行で済むのだ。これは嬉しい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* ** guard文でオプショナルバインディングをする例 */ //5個の価格を表示する関数 func printPrice(data:String) { guard var price = Int(data) else { return } print("5個で\(price * 5)です") } //メソッド呼び出し printPrice("120") // 実行結果 // 5個で600です |