すごいswitch文に出会った
Javaのリファクタリング案件でこんなコードに出会いました。
switch ( cmd ) {
case 0:
// 処理A
// fall through
case 1:
case 2:
// 処理B
break;
default:
// 処理C
break;
}
一見すると、 case 0 は 処理A のみを実行するように見えますが、よくみると、 case 0 には break がないので、実は 処理B も実行されるんです!
最初は、 break の書き忘れかな?と思いましたが、どうやら仕様通りの挙動でした。
フォールスルーという技だった
このように、意図的に break を省略する記法を フォールスルー(fall through) と言うそうです。よく見たらコメントにも書いてありますね。
if 文で置き換えてみた
このフォールスルーは、とても面白いテクニックですが、誤読を招きやすく、バグの温床になると思ったので、残念ですが if 文に置き換えることにしました。
if ( cmd == 0 ) {
// 処理A
}
if ( cmd <= 2 ) {
// 処理B
} else {
// 処理C
}
うーん、変更前の方がシンプルだったかな?微妙です。でも誤読の心配はなくなりました。
ただ、もし cmd が String 型だったら、こんな書き方はできないですね。悩みます。
もっと良い書き方があれば、どなたか教えてください。
フォールスルーできる言語とできない言語
他の言語の事情が気になったので、軽く調べてみました。
switch 文で break を省略すると fallthrough になる言語
- C
- C++
- JavaScript
- PHP
switch 文で break を省略すると怒られる言語
- C#
-
case文の中で何もしない場合は、breakを省略できる。 -
gotoで fallthrough のようなことはできる。
-
switch 文で明示的に fallthrough を指定する言語
- Perl (
nextを指定) - Swift (
fallthroughを指定) - Go (
fallthroughを指定)
switch 文に近い構文はあるが、 fallthrough はできない言語
- Ruby (
case文) - Scala (
match文) - Kotlin (
when文)
switch 文に相当する構文がない言語
- Python
条件を満たす全てのブロックが実行される言語
- PowerShell
- fall through はできない。
- 条件を満たす全てのブロックが実行される。
-
breakを使えば、打ち切ることができる。
言語によって色々ですね!勉強になりました。