Kotlin 中级篇(八):高阶函数详解与标准的高阶函数使用

本文介绍了Kotlin中的高阶函数,包括将函数作为参数和返回值的用法,并通过源码解析展示了如`map`, `run`, `with`, `apply`, `also`, `let`, `takeIf`, `takeUnless`等标准高阶函数的使用。同时,文章提供实例展示了如何自定义和应用高阶函数,帮助开发者理解并熟练运用这些功能提高代码效率和可读性。" 137405855,22893389,"JS对象空判断方法总结:JSON.stringify(), for...in, Object.keys()
摘要由CSDN通过智能技术生成

一、高阶函数介绍

Kotlin中,高阶函数即指:将函数用作一个函数的参数或者返回值的函数。

1.1、将函数用作函数参数的情况的高阶函数

这里介绍字符串中的sumBy{}高阶函数。先看一看源码

// sumBy函数的源码
public inline fun CharSequence.sumBy(selector: (Char) -> Int): Int {
    var sum: Int = 0
    for (element in this) {
        sum += selector(element)
    }
    return sum
}
复制代码

源码说明:

  1. 大家这里可以不必纠结inline,和sumBy函数前面的CharSequence.。因为这是Koltin中的内联函数扩展功能。在后面的章节中会给大家讲解到的。这里主要分析高阶函数,故而这里不多做分析。
  2. 该函数返回一个Int类型的值。并且接受了一个selector()函数作为该函数的参数。其中,selector()函数接受一个Char类型的参数,并且返回一个Int类型的值。
  3. 定义一个sum变量,并且循环这个字符串,循环一次调用一次selector()函数并加上sum。用作累加。其中this关键字代表字符串本身。

所以这个函数的作用是:把字符串中的每一个字符转换为Int的值,用于累加,最后返回累加的值

例:

val testStr = "abc"
val sum = testStr.sumBy { it.toInt() }
println(sum)
复制代码

输出结果为:

294  // 因为字符a对应的值为97,b对应98,c对应99,故而该值即为 97 + 98 + 99 = 294
复制代码

1.2、将函数用作一个函数的返回值的高阶函数。

这里使用官网上的一个例子来讲解。lock()函数,先看一看他的源码实现

fun <T> lock(lock: Lock, body: () -> T): T {
    lock.lock()
    try {
        return body()
    }
    finally {
        lock.unlock()
    }
}
复制代码

源码说明:

  1. 这其中用到了kotlin泛型的知识点,这里赞不考虑。我会在后续的文章为大家讲解。
  2. 从源码可以看出,该函数接受一个Lock类型的变量作为参数1,并且接受一个无参且返回类型为T的函数作为参数2.
  3. 该函数的返回值为一个函数,我们可以看这一句代码return body()可以看出。

例:使用lock函数,下面的代码都是伪代码,我就是按照官网的例子直接拿过来用的

fun toBeSynchronized() = sharedResource.operation()
val result = lock(lock, ::toBeSynchronized)    
复制代码

其中,::toBeSynchronized即为对函数toBeSynchronized()的引用,其中关于双冒号::的使用在这里不做讨论与讲解。

上面的写法也可以写作:

val result = lock(lock, {sharedResource.operation()} )
复制代码

1.3、高阶函数的使用

在上面的两个例子中,我们出现了str.sumBy{ it.toInt }这样的写法。其实这样的写法在前一章节Lambda使用中已经讲解过了。这里主要讲高阶函数中对Lambda语法的简写。

从上面的例子我们的写法应该是这样的:

str.sumBy( { it.toInt } )
复制代码

但是根据Kotlin中的约定,即当函数中只有一个函数作为参数,并且您使用了lambda表达式作为相应的参数,则可以省略函数的小括号()。故而我们可以写成:

str.sumBy{ it.toInt }
复制代码

还有一个约定,即当函数的最后一个参数是一个函数,并且你传递一个lambda表达式作为相应的参数,则可以在圆括号之外指定它。故而上面例2中的代码我们可写成:

val result = lock(lock){
     sharedResource.operation()
}
复制代码

二、自定义高阶函数

我记得在上一章节中我写了一个例子:

// 源代码
fun test(a : Int , b : Int) : Int{
    return a + b
}

fun sum(num1 : Int , num2 : Int) : Int{
    return num1 + num2
}

// 调用
test(10,sum(3,5)) // 结果为:18

// lambda
fun test(a : Int , b : (num1 : Int , num2 : Int) -> Int) : Int{
    return a + b.invoke(3,5)
}

// 调用
test(10,{ num1: Int, num2: Int ->  num1 + num2 })  // 结果为:18
复制代码

可以看出上面的代码中,直接在我的方法体中写死了数值,这在开发中是很不合理的,并且也不会这么写。上面的例子只是在阐述Lambda的语法。接下来我另举一

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值