iT邦幫忙

2022 iThome 鐵人賽

DAY 15
0
Mobile Development

新手向Android&Kotlin學習紀錄30天系列 第 15

第15天 kotlin小學堂(4) 控制流程 : if/else 、 when

  • 分享至 

  • xImage
  •  

邏輯控制

程式碼執行順序是由上往下執行,但是這種方法不可能滿足所有需求,這時候就需要靠一些條件語句(if/else條件語句、when條件語句)或循環語句(for循環、while循環)來控制程式碼該怎麼執行了。

if/else語句和運算式、when運算式可允許開發人員編寫各種條件來控制程式碼在符合或不符合條件的情況下該怎麼運行。

if/else條件語句

顧名思義,是有條件的執行指定的程式碼,語法是這樣:

if(條件){
    //條件成立就執行的事
}else{
    //條件不成立要執行的事
}

if()中的條件可以不只一個,可以使用之前說過的邏輯運算子:

  • && : 兩者均要成立(true),如,if(a > 0 && a < b){...}
  • || : 兩者至少一個成立(true),如,if(a == b || a == 0){...}
  • ! : 表否定,不過盡量少用負面表述,條件分支一多容易使人疑惑(還記得大選綁公投的否定再否定的題目嗎?),如,if(!a){...}
    例子舉的有點爛,不過應該還可理解。

接下來都用單一條件來舉例比較容易理解:
比如說,考試分數大於等於60分及格,小於60分不及格,假設分數65分,將考試結果印出在控制台就可以寫這樣:

fun main() {
    val score = 65
    if (score >= 60){
        println("及格")
    }else{
        println("不及格")
    }
    //運行結果:及格    
}

上例來看的意思是當if()中score>=60這個條件被滿足時,就會println("及格"),如果分數是0~59分,就會執行else{}中的println("不及格")。本例分數是65,所以會執行println("及格"),應該不難理解。

if/else有返回值

再看下面這個例子,JoJo跟Dio比成績誰高,平手算Dio贏,贏家的成績將會被記錄在"theBestScore",照上面的模式可能寫出這樣:

fun main() {
    val dioScore = 85
    val joJoscore = 55
    var theBestScore = 0  
    if (joJoscore > dioScore) {
        theBestScore = joJoscore
    } else {
        theBestScore = dioScore
    }
    println("The best score is $theBestScore")
}

kotlin 的 if/else 是可以有返回值的,意思是上例可以寫成這樣:

...
var theBestScore = if (joJoscore > dioScore)joJoscore else dioScore   
println("The  winner's score is $theBestScore")
  1. 如果if/else的{}內只有一句的話可以省略這對花括號{}。
  2. 因為結果返回值給theBestScore,所以原本theBestScore = joJoscoretheBestScore = dioScore的"theBestScore ="也就不需要了。
  3. 程式碼少了好幾行,整體看起來較簡潔俐落。

多個條件分支

萬一條件分支不只兩個呢?看例子,又是JoJo考試,這次評等更細 ,100 ~ 90 : A等、89 ~ 75 : B等、74 ~ 60 : C等 、小於60 : D等。
JoJo忙著對付Dio,考了個70分:
可以在每層else的分支中繼續再次if/else下去形成巢狀:

val joJoscore = 70
    if(joJoscore >= 90){
        println("A等")
    }else{
        if(joJoscore >= 75){
            println("B等")
        }else{
            if(joJoscore >= 60){
                println("C等")
            }else{
                println("D等")
            }
        }
    }
     //運行結果:C等

這麼多層是否看得眼花撩亂? 那麼可以再改寫成下面這樣:
將else可以跟下層的if,合寫成 else if分支,可以長出很多else if分支。

        if (joJoscore >= 90) {
        println("A等")
    } else if (joJoscore >= 75) {
        println("B等")
    } else if (joJoscore >= 60) {
        println("C等")
    } else {
        println("D等")
    }
    

太多else if 分支的時候,有沒有其他寫法? 有的,接著看下去

when 條件語句

承上例,也可使用when條件語句。
我們先來講講when條件語句怎麼使用,

//有參數
when(參數){
    匹配值 -> {執行程式碼}
    .
    .
    .
    else ->{執行程式碼}
}
//或不傳參數
when{
    匹配值 -> {執行程式碼}
    .
    .
    .
    else ->{執行程式碼} 
}
// ->後面{執行程式碼}的{},若只有一行程式碼的話可以省略

知道了基本語法,上面例子可以用when條件語句改寫成:

val joJoscore = 70
    when (joJoscore) {
        //90..100表示range(包含90、100),遞減的話要寫作 100 downTo 90
        in 90..100 -> println("A等")  
        in 75..89 -> println("B等")
        in 60..74 -> println("C等")
        else -> println("D等")
    }
//或是無參數
when{
        joJoscore >= 90 -> println("A等")
        joJoscore >= 75 -> println("B等")
        joJoscore >= 60 -> println("C等")
        else -> println("D等")
    }

when按順序將其參數與所有分支匹配,直到滿足某個分支條件。
在分支無法覆蓋所有情況下,else分支是必須要的。

when語句同樣可以像if/else那像有返回值,直接回傳一個值給變數。仍然以成績等第為例,將JoJo成績存入 level變數中可以寫成這樣:

//上面任一種寫法都可,println()就可以提取出來列印level這儲存了結果的變數即可。
    val level = when (joJoscore) {
        in 90..100 -> "A等"
        in 75..89 -> "B等"
        in 60..74 -> "C等"
        else -> "D等"
    }
    println("level: $level")

星期一到星期日穿什麼

如果貴族JoJo每天都有自己的luckyColor需要配合穿搭,但有些天會重複,如週一、三、五紅色、周二、四:藍色、週六、日:綠色,這樣條件依照剛剛學的不就會有週一到週日7個分支?

    var daysOfTheWeek = "Monday"
    val luckyColor = when(daysOfTheWeek){
        "Monday"     -> "red"
        "Tuesday"    -> "blue"
        "Wednesday"  -> "red"
        "Thursday"   -> "blue"
        "Friday"     -> "red"
        "Saturday"   -> "green"
        "Sunday"     -> "green"
        else         -> "再說一次,星期幾^^?"
    }
    println("$daysOfTheWeek luckyColor : $luckyColor") // 結果:Monday luckyColor : red

這樣也太囉嗦了吧,when可以再將同樣結論的匹配條件以「,」隔開寫成:

    var daysOfTheWeek = "Monday"
    val luckyColor = when(daysOfTheWeek){
        "Monday","Wednesday","Friday" -> "red"
        "Tuesday","Thursday",         -> "blue"
        "Saturday", "Sunday"          -> "green"
        else                          -> "再說一次,星期幾^^?"
    }
    println("$daysOfTheWeek luckyColor : $luckyColor")

喔耶
但是每次都要使用else,但有時候else帶來很多困擾,比如,星期明確就是一到日,哪來的else?,這時候,也可以使用enum class或sealed class,將所有情形列出,讓when 知道這已經是所有的情況,就不需要使用else囉
如:

//enum class 是用來儲存常數的列舉類別
enum class DaysOfTheWeek{
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

fun main() {
    var today = DaysOfTheWeek.FRIDAY
    val luckyColor = when(today){
        DaysOfTheWeek.MONDAY, DaysOfTheWeek.WEDNESDAY, DaysOfTheWeek.FRIDAY -> "red"
        DaysOfTheWeek.TUESDAY,DaysOfTheWeek.THURSDAY -> "blue"
        DaysOfTheWeek.SATURDAY,DaysOfTheWeek.SUNDAY -> "green"
    }
    println("$today Lucky Color : $luckyColor")
    //結果: FRIDAY Lucky Color : red
}

T.G.I.F.,明天見。


上一篇
第14天 Kotlin小學堂(3) : 那些運算子
下一篇
第16天 kotlin小學堂(5) 控制流程 : for loop、while loop
系列文
新手向Android&Kotlin學習紀錄30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言