Kotlin實戰【三】表示與選擇

南方吳彥祖_藍斯發表於2021-11-04

前言

本章我們將學習怎麼樣在Kotlin中透過列舉和when實現表示與選擇。

一 、表示與選擇之列舉

1.1列舉的定義

我們來看一下java中的用法:

public enum Color
{
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}1234

kotlin中的用法:

enum class Color {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}123

你會發現kotlin中使用enum同時還要使用class這與java中不同,思考下這是為什麼?

知識點

在Kotlin中,enum就是**所謂的軟關鍵詞(soft keyword):**當它放置在class關鍵詞之前,它才有特有的意義。但是你可以在其他的地方,把它當成常規的名字使用。
class仍然是一個關鍵字,要繼續使用clazzName之類的來宣告變數。
與java相同,列舉中可以宣告屬性和方法

1.2 帶屬性的列舉類

先看看java中的程式碼:

public enum Color
{
    RED(255, 0, 0), //當每個變數建立的時候,指定屬性值
    ORANGE(255, 165, 0), //逗號是必須的
    YELLOW(255, 255, 0),
    GREEN(0, 255, 0),
    BLUE(0, 0, 255),
    INDIGO(75, 0, 130),
    VIOLET(238, 130, 238);
    private int r;
    private int g;
    private int b;
    Color(int r, int g, int b)
    {
        this.r = r;
        this.g = g;
        this.b = b;
    }
    public int getRGB(){
        return (r * 256 + g * 256 + b*256);
    }
    public int getR()
    {
        return r;
    }
    public int getG()
    {
        return g;
    }
    public int getB()
    {
        return b;
    }
}12345678910111213141516171819202122232425262728293031323334353637383940

是不是超級多,再來看看kotlin,是不是少了好多,瞬間清爽了很多

enum class Color(
        val r: Int, val g: Int, val b: Int //宣告列舉常量的屬性
) {
    RED(255, 0, 0), //當每個變數建立的時候,指定屬性值
    ORANGE(255, 165, 0), //逗號是必須的
    YELLOW(255, 255, 0),
    GREEN(0, 255, 0),
    BLUE(0, 0, 255),
    INDIGO(75, 0, 130),
    VIOLET(238, 130, 238);
    fun rgb() = (r * 256 + g * 256 + b*256)//定義列舉的方法
}123456789101112

從兩個例子中可以看出,當你定義一個列舉常量,你需要為它提供屬性值。

這個例子中展示了Kotlin語法唯一需要分號的地方:在列舉類中如果你定義任何方法,分號區分了列舉常量列表和方法宣告。

接下來我們看一下列舉的處理:

二 、表示與選擇之When

2.1 使用“when”來處理列舉

接下來我們使用when選擇列舉,我們輸入一個顏色,返回對應的一個字串

fun getMnemonic(color: Color) =   //直接返回一個“when”的表示式
    when (color) {                //如果顏色等於列舉常量,返回響應的字串
        Color.RED -> "Richard"
        Color.ORANGE -> "Of"
        Color.YELLOW -> "York"
        Color.GREEN -> "Gave"
        Color.BLUE -> "Battle"
        Color.INDIGO -> "In"
        Color.VIOLET -> "Vain"
    }
println(getMnemonic(Color.BLUE)) // Battle123456789101112

上面程式碼我們可以處,你不需要為每個分支寫break語句(在java中遺漏break通常會導致bug)。

可以吧多個值合併到同一個分支,只需要逗號隔開。

如下:

fun getWarmth(color: Color) = when(color) {
    Color.RED, Color.ORANGE, Color.YELLOW -> "warm"
    Color.GREEN -> "neutral"
    Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold"
}
 println(getWarmth(Color.ORANGE)) //warm123456

上面的例子用全名來使用列舉常量,指定Color列舉類名。你可以用匯入常量來簡化程式碼:

import ch02.colors.Color //匯入宣告在另外一個包的Color類
import ch02.colors.Color.*//用名字顯示匯入列舉常量
fun getWarmth(color: Color) = when(color) {
    RED, ORANGE, YELLOW -> "warm" //用名字匯入常量
    GREEN -> "neutral"
    BLUE, INDIGO, VIOLET -> "cold"
}12345678

2.2 在"when"結構中使用任意物件

kotlin中的when結構比java中的switch強大得多。switch必須要求使用常量(列舉常量、字串或者數字字面值)作為分支條件,而when可以使用任何物件。

下面我們寫一個混合兩者顏色的函式:

fun mix(c1: Color, c2: Color) =
    when (setOf(c1, c2)) {//when表示式的引數可以是任何例項,用來被分支條件檢查
        setOf(RED, YELLOW) -> ORANGE//列舉可以混合的顏色對
        setOf(YELLOW, BLUE) -> GREEN
        setOf(BLUE, VIOLET) -> INDIGO
        else -> throw Exception("Dirty color")//執行這個,如果沒有分支可以匹配
    }
println(mix(BLUE, YELLOW))//GREEN12345678

Kotlin標準庫中含有一個setOf的函式,用來建立Set,包含引數指定的例項;一個set是一個集合,它的項的次序並不重要。所以,如果setOf(c1, c2)和setOf(RED, YELLOW)是相等的,那麼意味著要不然c1是RED和c2是YELLOW,或者相反。

2.3 使用不帶引數的when

上面的例子有點效率低下,因為每次你呼叫這個函式,它都會建立幾個Set例項,僅僅是用在檢查兩個顏色是否匹配另外兩個顏色。正常情況下,通常不是個問題。但是如果這個函式經常被呼叫,那麼為了避免GC,值得用另外一種方式來重寫這個程式碼。你可以用不帶引數的when表示式完成。程式碼雖然可讀性差一點,但是這是為了達到更好效能付出的代價。

fun mixOptimized(c1: Color, c2: Color) =
    //沒有實參傳給when
    when {
        (c1 == RED && c2 == YELLOW) || (c1 == YELLOW && c2 == RED) -> ORANGE
        (c1 == YELLOW && c2 == BLUE) || (c1 == BLUE && c2 == YELLOW) -> GREEN
        (c1 == BLUE && c2 == VIOLET) || (c1 == VIOLET && c2 == BLUE) -> INDIGO
        else -> throw Exception("Dirty color")
    }
println(mixOptimized(BLUE, YELLOW)) //GREEN123456789

2.4 程式碼塊作為"if"和"when"的分支

if和when都可以用程式碼塊作為分支。

在這個例子中,程式碼塊中最後最後一個表示式作為結果。如果你想在例子函式中加日誌,你可以在程式碼塊中完成,並用最後一個值返回。

fun evalWithLogging(e: Expr): Int =
    when (e) {
        is Num -> {
            println("num: ${e.value}")
            e.value //如果e是Num型別,這是程式碼塊最後一個表示式,並被返回
        }
        is Sum -> {
            val left = evalWithLogging(e.left)
            val right = evalWithLogging(e.right)
            println("sum: $left + $right")
            left + right//如果表示式被返回當e是Sum型別
        }
        else -> throw IllegalArgumentException("Unknown expression")
    }
    println(evalWithLogging(Sum(Sum(Num(1), Num(2)), Num(4))))
    //num: 1
    //num: 2
    //sum: 1 + 2
    //num: 4
    //sum: 3 + 4
    //7123456789101112131415161718192021

規則 :“程式碼塊中最後一個表示式是返回值”,在所有使用程式碼塊並期望得到一個結果的地方成立。

現在已經學會了如何正確從眾多選項中作出選擇,下一章我們一起去看下如何迭代事物。


文章轉自 https://cloud.tencent.com/developer/article/1385735 如有侵權,請聯絡刪除。


相關影片推薦:

Android 效能最佳化學習【二】:APP啟動速度最佳化_嗶哩嗶哩_bilibili
【Android進階系統學習】:位元組碼插樁技術實現自動化方法耗時記錄_嗶哩嗶哩_bilibili
Android 效能最佳化學習【二】:APP啟動速度最佳化_嗶哩嗶哩_bilibili
【Android面試專題】:面試又被問到程式間通訊,你卻連Binder是什麼都不知道?_嗶哩嗶哩_bilibili
BAT面試技巧——Android面試必問的網路程式設計你瞭解多少?_嗶哩嗶哩_bilibili


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69983917/viewspace-2840608/,如需轉載,請註明出處,否則將追究法律責任。

相關文章