Kotlin進階知識(八)——高階函數中的控制流

1、lambda中的返回語句:從一個封閉的函數返回

  • 在一個普通循環中使用return
fun lookForAlice(people: List<PersonNew>) {
    for(person in people) {
        if(person.name == "Alice") {
            println("Found")
            return
        }
    }
    // 若是「people」中沒有Alice,這一行就會被打印出來
    println("Alice is not found")
}

fun lookForAliceTest() {
    lookForAlice(people)
}

// 輸出結果
Found!
複製代碼
  • 在傳遞給forEachlambda中使用return
fun lookForAliceByForEach(people: List<PersonNew>){
    people.forEach {
        if(it.name == "Alice") {
            println("Found!")
            return
        }
    }
    println("Alice is not found")
}

fun lookForAliceByForEachTest() {
    lookForAliceByForEach(people)
}
複製代碼

非局部返回:在lambda中使用return關鍵字,它會從調用lambda的函數中返回,並不僅是從lambda中返回markdown

注意非局部返回,是從一個比包含return的代碼塊更大的代碼塊返回了。app

注意:只有在以lambda做爲參數的函數是內聯函數的時候才能從更外層的函數返回。函數

在一個非內聯函數lambda使用return表達式不容許的。一個非內聯函數能夠把傳給它的lambda保存在變量中,以便在函數返回之後能夠繼續使用,這個時候lambda想要去影響函數的返回已經太晚了。ui

2、從lambda返回:使用標籤返回

能夠在lambda表達式中使用局部返回。lambda中的局部返回for循環中的break表達式類似。它會終止lambda的執行,並接着從調用lambda的代碼處執行。this

要區分局部返回和非局部返回,要用到標籤。想從一個lambda表達式處返回你能夠標記它,而後在return關鍵字後面引用這個標籤。spa

  • 用一個標籤實現局部返回
fun lookForAliceByLabel(people: List<PersonNew>){
    people.forEach label@ {
        // return@label引用了
        if(it.name == "Alice") return@label
    }
    // 這一行老是會被打印出來
    println("Alice might be somewhere")
}

fun lookForAliceByLabelTest() {
    lookForAliceByLabel(people)
}

// 輸出結果
Alice might be somewhere
複製代碼
  • 標記一個lambda表達式,在lambda花括號以前放一個標記名(能夠是任何標識符),接着放要給**@字符**。code

  • 要從一個**lambda返回**,在**return關鍵字後放一個@符號**,接着放標籤名,如圖1:orm

圖1:用「@」符號標記一個標籤從一個lambda返回

  • 用函數名做爲return標籤
fun lookForAliceByLabel1(people: List<PersonNew>) {
    people.forEach {
        // return@forEach 從lambda表達式返回
        if(it.name == "Alice") return@forEach
    }
    println("Alice might be somewhere")
}
複製代碼

顯式地指定了**lambda表達式的標籤**,再使用函數名做爲標籤沒有任何效果。一個lambda表達式的標籤數量不能多於一個對象

  • 帶標籤的「this」表達式
fun lambdaTest() {
    // 這個lambda的隱式接受者能夠經過this@sb訪問
    println(StringBuilder().apply sb@ {
        // 「this」 指向做用域內最近的隱式接受者
        listOf(1, 2, 3).apply {
            // 全部隱式接受者均可以被訪問,外層的接受者經過顯式的標籤訪問
            this@sb.append(this.toString())
        }
    })
}
複製代碼

一樣的規則也適用於**this表達式的標籤**,帶接受者的lambda——包含一個隱式上下文對象的lambda能夠經過一個this引用去訪問。作用域

和return表達式中使用標籤同樣,能夠顯示地指定lambda表達式的標籤,也可使用函數名做爲標籤。

3、匿名函數:默認使用局部返回

匿名返回是一種不一樣的用於編寫傳遞給函數的代碼塊的方式。

  • 在匿名函數彙總使用return
fun lookForAliceByAnonymousFunction(people: List<PersonNew>) {
    people.forEach(fun (person) {
        // 使用匿名函數取代lambda表達式
        if(person.name == "Alice") return

        // 「return」指向最近的函數:一個匿名函數
        println("${person.name} is not Alice")
    })
}

fun lookForAliceByAnonymousFunctionTest() {
    lookForAliceByAnonymousFunction(people)
}

// 輸出結果
Bob is not Alice
複製代碼

匿名函數看起來跟普通函數類似,除了它的名字和參數類型被省略了外。

匿名函數中,不帶標籤return表達式會從匿名函數返回,而不是從包含匿名函數的函數返回

這條規則很簡單:

  • return最近使用fun關鍵字聲明函數返回。
  • lambda表達式沒有使用**fun關鍵字**,因此lambda中的return從最外層的函數返回
相關文章
相關標籤/搜索