服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

Kotlin中Lambda表达式及其简化

日期: 来源:冰岩作坊收集编辑:郝琳

在Kotlin编程中,lambda表达式的应用非常常见,这篇文章用来介绍一下怎样用lambda表达式定义函数,用lambda表达式进行函数传参,以及简化lambda表达式

参考文档: https://developer.android.com

用lambda表达式定义函数

先来看一个最简单的例子:

val trick={
    println("No treats!")
}

关键点:

1.lambda表达式的结果是一个值,因此可以直接将其存储在变量中(即上图中的trick中)

2."="后面即为lambda表达式,大括号中的内容为函数正文

怎样调用

fun main(){
    val trickFunction=trick//kotlin的推导机制可以判断出trick为函数类型
    trick()
    trickFunction()
}

加上参数和返回值

刚才的trick函数非常简单,它的数据类型为()->Unit,()为空,代表它不接受任何参数,返回值类型为Unit,代表它不返回任何内容,所以它较为完整的写法是这样的

val treat:()->Unit={
    println("Have a treat!")
}

那么现在来看一个复杂的函数

val trick={
    println("No treats!")
}

fun trickOrTreat(isTrick:Boolean):()->Unit{
    if(isTrick){
        return trick
    }else{
        return treat
    }
}

首先,我们又用lambda表达式定义了一个简单的函数trick,在trickOrTreat()函数的正文中,设置一个if语句,使其在 isTricktrue 时返回 trick() 函数,并在 isTrick 为 false 时返回 treat() 函数。

代码逻辑理好了,现在来测试一下:

fun main(){
    val treatFunction=trickOrTreat(false)
    val trickFunction=trickOrTreat(true)
    treatFunction()
    trcikFunction()
}

输出结果如下:

Have a treat!
No treats!

在刚才的trickOrtreat函数中,我们将函数作为返回值,那么该怎样将函数作为参数传递呢?

举个栗子:

fun trickOrTreat(isTrick:Boolean,extraTreat:(Int)->String):()->Unit{
    if(isTrick){
        return trick
    }else{
        println(extraTreat(5))
        return treat
    }
}

在这个函数中,添加了类型为(Int)->String的extraTreat函数参数,这代表trickOrTreat函数接受一个函数作为参数,其参数类型为Int返回值类型为String

那么现在我们来编写两个这样的函数来进行测试

fun main(){
    val coins:(Int)->String={
        quantity->"$quantity auarters"
    }//quantity为Int参数(可省略),lambda表达式不支持return语句,函数中最后一个表达式的结果将成为返回值,详情下回分解
    val cupcake:(Int)->String={
        quantity->"Have a cupcake!"
    }
    val treatFunction = trickOrTreat(false,coins)
    val trickFunction = trickOrTreat(true,cupcake)
    treatFunction()
    trickFunction()
}

main函数中,我们定义了两个以Int类型为参数,返回值为String的函数,并将其作为参数传入到trickOrTreat函数中。当 isTrickfalse 时,传入 coins() 函数。对于第二次调用,当 isTricktrue 时,传入 cupcake() 函数。

好了,现在我们已经掌握了如何将函数作为参数。但是如果我们不想传入函数呢?答案是把函数类型声明为可为null,方法很简单,用圆括号括住函数类型,并在后面接?符号

修改trickOrTreat函数:

fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit {
    if (isTrick) {
        return trick
    } else {
        if (extraTreat != null) {
            println(extraTreat(5))
        }
        return treat
    }
}

好了,现在extraTreat可以为空了,并且只有它不为空的情况下才会调用println(extraTreat(5))

总结:

  • Kotlin 中的函数是一级结构,可以视为数据类型。

  • lambda 表达式提供了一种用于编写函数的简写语法。

  • 您可以将函数类型传入其他函数。

  • 对于一个函数类型,您可以从另一个函数返回它。

  • lambda 表达式会返回最后一个表达式的值。

简化Lambda表达式

1.省略参数名称

我们依然以上文中的coins函数为例

val coins: (Int) -> String = {
    quantity->"$quantity quarters"
}

coins函数只接受一个Int类型的参数,我们完全可以省略quantity名称和->符号,因为·Kotlin会自动为其分配it名称,就像这样

val coins: (Int) -> String = {
    "$it quarters"
}

2.将lambda表达式直接传入函数

在上文中,我们将coins函数作为参数传入trickOrTreath函数中:

fun main() {
    val coins: (Int) -> String = {
        "$it quarters"
    }
    val treatFunction = trickOrTreat(false, coins)
}

我们可以看到,coins函数非常简短,并且只调用过一次,因此我们可以直接将lambda表达式传入其中,而不必再声明coins函数

fun main() {
    val treatFunction = trickOrTreat(false, { "$it quarters" })
    treatFunction()
}

使用尾随lambda语法

当lambda表达式作为传入的组后一个参数时,可以把它写在括号外面,这样看起来会更加简洁

val treatFunction = trickOrTreat(false) { "$it quarters" }

对比一下

最初代码:

fun main() {
    val coins: (Int) -> String = {
        quantity->"$quantity quarters"
    }
    val treatFunction = trickOrTreat(false, coins)
}

简化版:

fun main() {
 val treatFunction = trickOrTreat(false) { "$it quarters" }
}

这是lambda的一小步,是程序员的一大步

高阶函数

最后再简单说一下高阶函数,其实非常简单,高阶函数能够返回或接受另一个函数作为参数,例如,上篇文章中介绍的trickOrTreat() 函数就是一个高阶函数的示例,因为它接受 ((Int) -> String)? 类型的函数作为参数,并且返回了 () -> Unit 类型的函数。

fun trickOrTreat(isTrick: Boolean, extraTreat: ((Int) -> String)?): () -> Unit {
//接收函数作为参数
    if (isTrick) {
        return trick//返回函数
    } else {
        if (extraTreat != null) {
            println(extraTreat(5))
        }
        return treat//返回函数
    }
}

再来介绍一个非常有用的高阶函数:repeat

repeat(times: Int, action: (Int) -> Unit)

times 参数是操作应发生的次数。action 参数是一个接受单个 Int 参数并返回 Unit 类型的函数。action 函数的 Int 参数是到目前为止已执行的操作次数,例如第一次迭代的 0 参数或第二次迭代的 1 参数。您可以使用 repeat() 函数按指定次数重复执行代码,这与 for 循环类似。

使用示例:

fun main() {
    val treatFunction = trickOrTreat(false) { "$it quarters" }
    val trickFunction = trickOrTreat(true, null)
    repeat(4) {
        treatFunction()//对action函数使用尾随lambda语法
    }
    trickFunction()
}

运行后,treatFunction即可执行四次

总结

  • 只有一个参数的 lambda 表达式中,可以直接使用 it 标识符来引用它。
  • 如果调用函数的最后一个参数是函数类型,可以使用尾随 lambda 语法将 lambda 表达式移至最后一个圆括号后面。
  • 高阶函数是指接受函数作为参数或返回函数的函数。


相关阅读

  • 浅谈JS函数式编程

  • 高效搬砖——拆分、组合、复用我们不妨以一个栗子开始:这是Scott Sauyet所著《Favoring Curry》中一个在项目实战里遇到的问题。var data = { result: "SUCCESS", inte
  • 读库二十二条好汉,奉上二十二份推荐

  • 春节将至,读库也将开启放假模式。作为这一年的总结,我们向同事们发起了一份年度书单征集。为顾全大局,避免出现大家只谈论自家产品这种其乐融融的场面,我们做了小小的限定,只能推
  • 梵高的秋 | 跟着名画吃水果

  • 水果时节水果是大自然最甜蜜的语言。在这个丰收的季节,水果以其甘甜滋润着万物,也启迪了人们。荷兰中部小镇蒂尔盛产苹果、梨、覆盆子、樱桃等水果,享有“荷兰果园”的美称。这
  • 梵高活动 | 博物馆之夜,越夜越精彩

  • 2022博物馆之夜AMSTERDAM11月5日周六晚,又是一年一度的阿姆斯特丹博物馆之夜。夜幕降临之后,全城50多座大小博物馆焕发出全新活力。只需一张通票,你就可以进入所有博物馆,尽情体
  • 梵高征集 | 年底了,让梵高艺术壁纸陪伴你

  • 近期,梵高博物馆后台收到了不少想要高清壁纸的请求。宠粉的我们怎么能不听呢?今天我们就来发福利!我们从博物馆最受欢迎的作品中,选出十张关于自然的画作,裁剪成高清手机壁纸尺寸
  • 梵高季节 | 跟着画作谈恋爱

  • 浪漫季节法国印象派画家雷诺阿认为,一幅画应该是美丽的、可爱的、欢快的,因为生活中令人烦恼的事情已经够多了,不需要再费心去制造更多麻烦。因此,雷诺阿的每一幅画都洋溢着幸福

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四

最新文章

  • Kotlin中Lambda表达式及其简化

  • 在Kotlin编程中,lambda表达式的应用非常常见,这篇文章用来介绍一下怎样用lambda表达式定义函数,用lambda表达式进行函数传参,以及简化lambda表达式参考文档: https://developer.
  • 利用Spine制作简单2D骨骼动画

  • hi!这里是一个关于游戏中2D骨骼动画的小小分享。 在2D游戏中,我们经常可以看见各式各样的角色动画。动画能给游戏带来生机和灵气。创作一段美妙的动画,不仅需要强大的软件工
  • 标题党,不丢人

  • 当人们形容一篇媒体作品为“标题党”时,常常带有贬义的情感色彩。所谓标题党,通常认为是用夸张的标题吸引人点击查看,内容却不甚相干或严重失实的信息。譬如热衷于套用短平快模
  • 浅谈JS函数式编程

  • 高效搬砖——拆分、组合、复用我们不妨以一个栗子开始:这是Scott Sauyet所著《Favoring Curry》中一个在项目实战里遇到的问题。var data = { result: "SUCCESS", inte
  • 浅析B站用户体验

  • 文章着重从用户体验五要素分析“哔哩哔哩"。什么是“用户体验五要素”?在《用户体验要素》这本书中,作者加瑞特把影响用户体验的因素分为5个层次,即a.战略存在层;b.能力范围层;
  • 穿越沙丘 —— 2022 冰岩年刊

  • 亲爱的冰岩人们,你们好!时间来到2022年底,互联网进入深水区的趋势似乎仍在继续。作为一个互联网学生团队,冰岩作坊也和现在的互联网行业一样遇上了前所未有的发展瓶颈,努力寻找着