美文网首页Kotlin精选KotlinKotlin编程
Kotlin中的函数式编程(2):高阶函数与内联函数

Kotlin中的函数式编程(2):高阶函数与内联函数

作者: 黑心石 | 来源:发表于2017-10-30 20:38 被阅读37次

    在函数式编程中,允许采用变量保存函数,也可以将函数作为参数值或者返回值。因此,必然存在一种函数,它以另一个函数作为参数或者返回值,这种函数叫高阶函数

    函数类型

    正如上一节我们谈到的,函数也是有类型的,称为函数类型。声明函数类型,需要将函数参数类型放在一个括号中,紧接着是一个箭头和函数的返回类型,例如:

    声明函数类型

    当然,同普通变量一样,函数变量也是可以初始化的

    在Kotlin中,Unit类型用于表示函数不返回任何有用的值,例如:

    在了解了函数类型之后,我们可以定义高阶函数了,以下定义了一个将函数作为参数的高阶函数:

    函数接收一个以两个Int作为参数并且返回Int的函数,然后用这个函数求得2和3的运算结果

    把函数作为返回值也许不怎么常用,但是在某些条件下还是挺方便的,例如著名的策略模式(设计模式中的一种):

    返回函数的函数

    利用高阶函数去除重复代码

    在开发过程中我们常常需要进行多线程异步操作,当一个线程完成工作时通知另一个线程,最古老的方式是回调

    回调方式

    这意味着我们为了很简单的任务,需要编写大量的代码,更严重的是,如果这个任务还和其他任务有多线程协作,就会有新的回调,这将变成回调的地狱。从代码里可以看到,我们真正关心的只不过是这两个线程做了什么而已(两段代码),那么,我们有没有简化的方式呢?

    当然有,因为lambda代表的就是程序的一小段代码嘛:

    使用高阶函数封装异步操作

    现在我们可以直接调用runAsync函数进行异步操作了,当然,这个封装是有问题的,它只接受无参数值并且无返回值的函数,这个在不久的将来将会被改进,如果你熟悉RxJava的话,你应该对下面这个函数不陌生:

    具有返回值的异步封装

    这个函数表示了异步任务完成后主线程的工作,当然,要完全搞懂这个函数还需要一点其他的知识。

    通过内联函数消除lambda带来的运行时开销

    我们知道lambda表达式会编译成匿名类,而且在捕捉了外部变量后,会在调用的时候产生新的对象,那么,能不能消除这种额外开销呢?

    当一个函数被声明为inline时,它的函数体时内联的,函数体将被直接替换到函数被调用的地方

    例如,下面的两个函数是等价的:

    内联函数

    事实上,内联函数repeat函数在执行时会编译为repeat2的形态,这样就避免了匿名类的创建。

    那么所有的函数都可以被内联么?

    在内联的时候,作为参数的lambda表达式的函数体会被直接替换到最终生成的代码中。如果lambda在某个地方被保存起来供以后使用,则lambda表达式不能被内联,比如:

    func和repeat无法内联

    显然,传入的函数参数来自其他地方,系统在编译这个类的时候都不知道传入的函数func是什么,自然不可能进行直接替换

    由于内联函数是直接替换到最终的代码中,因此,它往往还可以捕获一些上下文信息,因此除了能减少匿名类的创建以外,它还有其他用途,我们将在未来谈到它。

    相关文章

      网友评论

        本文标题:Kotlin中的函数式编程(2):高阶函数与内联函数

        本文链接:https://www.haomeiwen.com/subject/afaypxtx.html