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从最外层的函数返回
相关文章
相关标签/搜索