目录
6.5 Kotlin课堂:高阶函数详解
学到这里,你已经可以算是完全入门Kotlin 编程了。因此,从本章的 Kotlin 课堂起,我们就将告别基础知识,开始转向Kotlin 的高级用法,从而进一步提升你的Kotlin 水平。
那么就从高阶函数开始吧。
6.5.1 定义高阶函数
高阶函数和 Lambda 的关系是密不可分的。在第2章快速入门 Kotlin 编程的时候,我们已经学习 了 Lambda 编程的基础知识,并且掌握了一些与集合相关的函数式 API 的用法,如 map、 filter函数等。另外,在第 3 章的 Kotlin 课堂中,我们又学习了 Kotlin 的标准函数,如 run、 apply函数等。
你有没有发现,这几个函数有一个共同的特点:它们都会要求我们传入一个 Lambda 表达式作为参数。像这种接收 Lambda 参数的函数就可以称为具有函数式编程风格的 API,而如果你想要 定义自己的函数式 API,那就得借助高阶函数来实现了,这也是我们本节 Kotlin 课堂所要重点学 习的内容。
首先来看一下高阶函数的定义。如果一个函数接收另一个函数作为参数,或者返回值的类型是另一个函数,那么该函数就称为高阶函数。
这个定义可能有点不太好理解,一个函数怎么能接收另一个函数作为参数呢?这就涉及另外一 个概念了:函数类型。我们知道,编程语言中有整型、布尔型等字段类型,而 Kotlin 又增加了一 个函数类型的概念。如果我们将这种函数类型添加到一个函数的参数声明或者返回值声明当 中,那么这就是一个高阶函数了。
接下来我们就学习一下如何定义一个函数类型。不同于定义一个普通的字段类型,函数类型的语法规则是有点特殊的,基本规则如下:
(String, Int) -> Unit
突然看到这样的语法规则,你一定一头雾水吧?不过不用担心,耐心听完我的解释之后,你就 能够轻松理解了。
既然是定义一个函数类型,那么最关键的就是要声明该函数接收什么参数,以及它的返回值是 什么。因此,-> 左边的部分就是用来声明该函数接收什么参数的,多个参数之间使用逗号隔 开,如果不接收任何参数,写一对空括号就可以了。而 -> 右边的部分用于声明该函数的返回值 是什么类型,如果没有返回值就使用 Unit,它大致相当于Java 中的 void。
现在将上述函数类型添加到某个函数的参数声明或者返回值声明上,那么这个函数就是一个高阶函数了,如下所示:
fun example(func: (String, Int) -> Unit) {
func("hello", 123)
}
可以看到,这里的 example() 函数接收了一个函数类型的参数,因此 example() 函数就是一个 高阶函数。而调用一个函数类型的参数,它的语法类似于调用一个普通的函数,只需要在参数 名的后面加上一对括号,并在括号中传入必要的参数即可。
现在我们已经了解了高阶函数的定义方式,但是这种函数具体有什么用途呢?由于高阶函数的用途实在是太广泛了,这里如果要让我简单概括一下的话,那就是高阶函数允许让函数类型的 参数来决定函数的执行逻辑。即使是同一个高阶函数,只要传入不同的函数类型参数,那么它 的执行逻辑和最终的返回结果就可能是完全不同的。为了详细说明这一点,下面我们来举一个 具体的例子。
这里我准备定义一个叫作 num1AndNum2() 的高阶函数,并让它接收两个整型和一个函数类型的 参数。我们会在 num1AndNum2() 函数中对传入的两个整型参数进行某种运算,并返回最终的运算结果,但是具体进行什么运算是由传入的函数类型参数决定的。
新建一个 HigherOrderFunction.kt 文件,然后在这个文件中编写如下代码:
fun num1AndNum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int {
val result = operation(num1,num2)
return result
}
这是一个非常简单的高阶函数,可能它并没有多少实际的意义,却是个很好的学习示例。 num1AndNum2() 函数的前两个参数没有什么需要解释的,第三个参数是一个接收两个整型参数 并且返回值也是整型的函数类型参数。在 num1AndNum2() 函数中,我们没有进行任何具体的运 算操作,而是将 num1 和 num2 参数传给了第三个函数类型参数,并获取它的返回值,最终将得到 的返回值返回。
现在高阶函数已经定义好了,那么我们该如何调用它呢?由于 num1AndNum2() 函数接收一个函数类型的参数,因此我们还得先定义与其函数类型相匹配的函数才行。在 HigherOrderFunction.kt 文件中添加如下代码:
fun plus(num1: Int, num2: Int): Int {
return num1 + num2
}
fun minus(num1: Int, num2: Int): Int {
return num1 - num2
}
这里定义了两个函数,并且这两个函数的参数声明和返回值声明都和 num1AndNum2() 函数中的函数类型参数是完全匹配的。其中,plus() 函数将两个参数相加并返回,minus() 函数将两个 参数相减并返回,分别对应了两种不同的运算操作。
有了上述函数之后,我们就可以调用 num1AndNum2() 函数了,在 main() 函数中编写如下代 码: