Kotlin高阶函数及Lambda表达式解析

时间:2022-09-04 19:12:11

在网上关于Kotlin的高阶函数和Lambda表达式的讲解大部分来自于Kotlin的官方文档,个人认为比较晦涩难懂。
本文从我的个人理解角度讲解一下应该如何理解高阶函数和Lambda表达式,希望能对正在学习Kotlin的同学有所帮助。

高阶函数是将函数用作参数或返回值的函数。

这是官方对高阶函数的定义,那么要理解高阶函数,第一要明确的概念是,在Kotlin里函数可以作为一种变量类型存在!!!
这非常的重要,能够理解这个,基本上后续的高阶函数的所有问题就都能够迎刃而解了。
函数可以作为一种变量类型存在是什么样的呢,就是在Kotlin里允许以下代码存在:
var function: ()->String
这句代码声明了一个变量,这个变量的类型是一个函数,这个函数的特征是参数列表为空,返回值为String。
大家想一下,对于一个函数来说可不就是可以用参数列表和返回值就能描述他的特点么,至于函数名则是相当于变量名,不属于特征的一部分。
如果你接受了上面的说法,那么你对高阶函数是将函数作为参数这半句话应该就能接受了。
那么当我们将一个函数作为参数使用时有两种情况,一种情况是我已经定义好了一个函数A,另一个高阶函数B中有一个和函数A特征一样的函数参数,那么我就可以在调用函数B时,将函数A作为参数传过去。代码如下。

fun funcA(arg: String){
    println("funcA's variable is $arg")
}

fun funcB(arg1: String, func: (arg: String)->Unit){ func(arg1) } fun main(args: Array<String>){ val funcVariable: (arg: String)->Unit = ::funcA
    funcB("test", funcVariable)
}

所以上面的代码会输出”funcA’s variable is test”。这实际就是在main方法里将funcA赋值给一个变量funcVariable(这个变量在声明的时候变量类型是对一个函数的特征值的描述:参数列表和返回值),然后调用funcB的时候,把这个函数变量当做参数使用了(能够使用的原因也当然是函数特征值是一致的)。
假如你理解了上面的代码,那么Lambda表达式就很容易理解了,也就是我要说的将一个函数作为参数使用时的第二种情况匿名函数。Lambda表达式实际就是一种匿名函数的用法。对于函数的特征在声明高阶函数时就已经确定了,以上面的例子来说就是

(arg: String)->Unit

那么在匿名调用的时候,我就不再重复的写一遍了,而是直接提供函数体。事实上,对于funcB来说他需要的也正是符合函数特征的函数体而已,所以在调用的时候可以直接上大括号,并在大括号里写函数体就好了。但是这个地方还有个问题,在写函数体的时候会用的这个函数的参数,那么在Kotlin里就加入了相应的语法”->”,在”->”的左侧程序员可以自己给匿名函数的参数起个名字,”->”的右侧写函数体,并且可以直接使用刚刚起名的参数。也就是一下这种用法。

fun funcB(arg1: String, func: (arg: String)->Unit){ func(arg1) } fun main(args: Array<String>){ funcB("test", { arg->println("funcA's variable is $arg") }) }

上面两个例子实际上是干了同一件事,只不过一个是先定义好了函数然后使用,另一个是在使用的时候现写一个匿名的函数实现。
好那么以上应该就解决了高阶函数的前一句定义,那么后一句定义呢?
高阶函数是如何将函数作为返回值的呢?
我的理解是将函数作为返回值使用的前提是你的高阶函数里用到了泛型。
先给一个将函数作为返回值的高阶函数例子吧。

fun <RESULT> returnAFunc(func: ()->RESULT): RESULT{ return func() }

这个高阶函数就是将一个函数作为了自己的返回值。这里用到了泛型,RESULT就是这个函数里不确定的返回值类型。在函数声明阶段这个RESULT的类型是不确定,只有在真正调用returnAFunc这个函数时,根据传进来的func的函数特征描述(特征描述包括参数列表和返回值类型)才能确定RESULT的类型,与func的返回值类型一致。所以returnAFunc的函数体里只能返回传进来的函数参数func(),这也就是高阶函数将函数作为返回值的意思了。
这个描述我认为挺准确的,细细分析下来也的确是这么回事,但是同时他也是很晦涩难懂的。
以上是我对Kotlin中高阶函数的理解,当然由于我没有分析过Kotlin的源码,只是从直观上进行的理解,可能会有偏差或者不准确地方,欢迎大家共同讨论。