天天看点

Kotlin高阶函数和Lambda表达式

高阶函数和Lambda表达式

高阶函数是接受函数作为参数或者将函数作为返回值的函数。我们可以将C语言中使用回调函数的函数称为高阶函数。

例如我们有一个数值处理函数

processNum()

,对于给定Int型数据,依次执行两个处理过程 proc1 和 proc2 :

fun processNum(num: Int, proc1: (Int) -> Int, proc2 (Int) -> Int): Int {
    return proce2(proc1(num))
}
           

如上,

processNum()

是高阶函数,它包含函数类型参数

proc1

proc2

高阶函数需要函数作为参数,这就要求调用时需要一个函数实参。如果在其他地方声明函数并在高阶函数调用处传入非常不利于代码阅读的连贯性(各种代码跳转很难阅读),并且有时函数的实现逻辑非常的简单,重新声明一个函数的大部分代码都是模板代码。这时Lambda表达式就有用了。

可以将Lambda理解为“字面值函数”。试想,如果在调用一个函数时我们已经知道了一个 Int 实参就是字面值 1 ,那么我们就可以直接使用1作为参数调用这个函数而不需要声明一个Int变量将它赋值为 1 然后再作为实参去调用函数! 使用Lambda表达式的思路与此类似:如果我们已经知道了这个函数参数的“样子”我们就可以直接用Lambda表达式表示出来作为实参,而不需要再声明一个函数并将函数作为实参!

Lambda表达式语法参考

it 语法糖

如果Lambda表达式只有一个参数那么可以省略该参数和

->

并可以在Lambda表达式中使用

it

来代替该参数。在Lambda的唯一参数被省略时,

it

用来代表该参数!

Lambda 表达式和闭包

Lambda表达式能够访问其闭包中的变量,不同于Java,Kotlin还可以修改这些变量。如果

this

在闭包中有定义,那么在Lambda表达式中也可以使用this。

Lambda表达式中的

this

需要特别注意,如果为Lambda表达式指定了 receiver 那么在Lambda表达式中

this

代表它的 receiver,否则

this

与其闭包中的

this

等价。 如果需要访问Lambda表达式闭包中的变量,而这个变量名和其receiver中的变量名冲突,此时需要

this@<closureName>.<varNmae>

语法来指明该变量是Lambda表达式闭包中的变量。如果情况复杂分不清

this

指向谁,那么总是使用

this@

是不容易出错的做法!

Kotlin 标准库中的高阶函数

run 函数

不带 receiver 的

run

函数执行参数中的可执行对象,将返回值作为

run

的返回值:

/**
 * Calls the specified function [block] and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R = block()
           

带 receiver 的

run

将上下文中的

this

指向 receiver 并执行参数中的可执行对象,将返回值作为

run

的返回值:

/**
 * Calls the specified function [block] with `this` value as its receiver and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R = block()
           

with 函数

换了个写法的带 receiver 的

run

函数:

/**
 * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
           

apply 函数

类似带 receiver 的

run

函数,可执行对象参数的执行上下文中

this

被设置为receiver。不同的是apply返回 receiver 本身。

/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
           

apply

函数将处理过程“应用”到 receiver 上并返回 receiver 本身,这适用于修改 receiver 的场景,比如将某个函数的返回值修正一下。

let 函数

let

函数将 receiver 作为其可执行对象参数的实参传入并执行可执行对象,返回值是可执行对象的返回值:

/**
 * Calls the specified function [block] with `this` value as its argument and returns its result.
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
           

结合 it语法糖。一般来说在写传入

let

函数的Lambda表达式参数时往往使用

it

表示

let

的 receiver 。

also 函数

它和

let

函数的关系类似于

apply

和带 receiver的

run

函数的关系。

also

函数将 receiver 作为其可执行参数的实参传入并执行可执行对象,但是其返回值为 receiver 本身

/**
 * Calls the specified function [block] with `this` value as its argument and returns `this` value.
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
           

如何选择?

:)

Kotlin 容器类相关高阶函数

继续阅读