剛轉換到 Kotlin 時,不知道有沒有人跟我一樣覺得很奇怪,為什麼 Kotlin 要 “重新發明” switch,並把它命名為 「when」呢?
我認為原因是 1. when 不只是有 switch 的功能, 他還包含了更多原本 switch 所沒有支持的,為了避免誤會,所以選用新的名稱。2. Kotlin 是一個很重視語意的語言,也就是說,它設計方向讓程式碼可以更容易被讀懂,所以使用 when (當),來替代 switch (交換)。
更佳的語意
首先,如果你完全不會寫 Kotlin,看到下方的程式碼,不知道你能不能第一時間把這個函式的意思解讀出來。
函式的意思如下:
- 函數名稱為 examScore,其中有一個參數: score,它的型態是整數型態 (Int)
- 當(when) 分數(score) 在
(1) 0~59 之間,列印 “ You are not pass the exam!!”
(2) 60~69 之間,列印 “You almost fail the exam!”
(3) 70~89 之間,列印 “Not bad!”
(4) 90~99之間,列印 “Very good!”
(5) 100 ,列印 “Perfect!”
如果你用 Kotlin show bytecode 把該段程式碼轉回 Java ,你會發現,這段程式碼不是用 switch 來寫的,而是使用雙重 if 來確認數字是否在範圍內。
熟悉 Java 的朋友,一定都了解 switch 是使用 case 來判斷單一條件。比如說下方的這個範例,
我們可以用 switch 來判斷 enum 值。
每一個 case 的後方,都是接一個 enum 值,當輸入的值恰好與 case 的值相同時,就會進入 case 的執行範圍內,然後在下面的 break 結束。break 可以不需要加,如果該加時卻忘記加,那麼奇妙的時刻就會出現了,當沒有 break 阻擋運行的流程時,程式的流程就會走到下一個 case 的運算中,然後就會發生意想不到的情況。
用 Kotlin 改寫的程式碼如下
乍看之下,好像只是排版的不同,其實有幾個地方值得討論:
- 當條件內只有一行運算式的時候, switch 需要花費三行才能完成這個條件判斷,而 when 只需要一行就可以完成。
- when 不需要 break,所以不會有忘記加 break 時發生的靈異現象了。
- when 的條件全部都在左手邊,運算式都放在右邊。反之,switch 的條件在左邊,而運算式是在下面一行,然後有一個縮排,在視覺上, when 的程式碼比較容易了解。
更強的功能
前面有提到, switch 的 case 只能針對單一靜態值來做判斷,例如整數、enum 值等等… 如果想要在case 裡面同時判斷多個條件,用 switch 的 case 是沒有辦法做到的。
when 的條件式可以是一個表達式 (expression)
如同第一個範例所示範的,我們可以利用 when 來判斷一個數值的區間,而不只是一個靜態的數值。
其他還有,我們可以判斷是否為某一類別,
when 可以替代 if-else if
如下例, oddCheck 是用來判斷輸入的 Int 是奇數還是偶數。
when 不包含判斷的值時,就轉身成為 if-else 判斷式。
替換的原因很簡單,就是用 when 看起來比較直覺。所有的判斷式都在左邊,運算式都在右邊。
when 也是一個表達式
因為是一個表達式,所以我們可以將 when 指派到任何一個變數上,如下
可以發現,我們在這邊直接將 when 指派給 fun multipleCheck(i:Int)
當呼叫 multiplesCheck
時,會判斷輸入的值是否為 3 的倍數,或是 5 的倍數,若都不是,則會會回傳 -1。
結論
when 的出現,解決在 Java 上 switch 不足、不夠完善的地方,例如,break 可加可不加,但是不加很可能會造成程式的運作流程出現問題。條件式與運算式都在同一邊,容易造成視覺上混淆。
when 的判斷式能夠使用表達式,比起 switch 的靜態值,能夠有更廣、更豐富的應用,甚至在使用上也可以替換掉 if-else。
when 本身也是一個表達式,所以可以指派到一個變數上,在複用上就可以更方便使用。
使用 when,我們可以得到更清楚的語意,加上 when 的強大的判斷能力以及靈活性,讓判斷式可以更多變。
就讓 when 把我們的判斷式變得更易懂吧。
本篇文章如果有幫助到你,請拍手👏鼓勵我吧~ 小祕技:拍手按鈕按著可以連續拍喔。
參考
https://kotlinlang.org/docs/control-flow.html#when-expression