Kotlin基础语法 十三、lamdba表达式解析四(语法篇)

一、Lambda表达式语法

回顾上一篇,我们在某个地方需要运行一个函数,我们只知道这个函数的参数类型和返回值类型(参数类型加返回值类型构成了 kotlin一种特殊的数据类型:函数类型),但函数具体执行什么操作我们并不关心,所以我们动态的传递一个满足参数类型和返回值类型条件的函数,但只有对象才能作为参数传递,所以我们通过双冒号或匿名函数 来实现一个函数类型的对象,但这两种方式代码比较繁琐,为了简化代码量,使代码简洁明了,我们引入了Lambda表达式,所以Lambda表达式的本质其实是函数类型的对象,我们真正的诉求就是想要一个动态设置的方法。

示例:现在有一个方法a,该方法的参数类型是一个函数类型

fun a(fb : (Int , String) -> String) {

}

为了能调用方法a,我们需要传入一个函数类型的对象,
我们一般有两种方法:

  1. 可以使用双冒号:
fun b(p1 : Int , p2 : String) : String {
    return p2 + p1
}
a(::b)
  1. 使用匿名函数
val b : (Int , String) -> String = fun(p1 : Int , p2 : String) : String {
    return p2 + p1
}
a(b)

当然也可以直接把匿名函数传进去:

a(fun(p1 : Int , p2 : String) : String {
    return p2 + p1
})

可以看到匿名函数的方式过于繁琐了,接下来我们引入Lambda表达式进行简化

1. )Lambda表达式格式如下:
{参数1:参数类型,参数2:参数类型,… -> 执行代码块 }

注意:执行代码块里最后一行表达式就是Lambda表达式的返回值
,该表达式的返回类型必须与声明的返回值类型一致。

所以上面的匿名函数我们可以用Lambda表达式表示为:

a({ p1 : Int , p2 : String ->
    p2 + p1
})

2.)当我们已经显示声明lambda的函数类型时,可以省去lambda参数列表中参数的类型
所以可以简化为:

a({ p1 , p2 ->
    p2 + p1
})

3.)当lambda表达式作为函数调用的最后一个实参,可以将它放在括号外边
所以可以简化为:

a() { p1 , p2 ->
    p2 + p1
}

4.)当lambda是函数唯一的实参时,还可以将函数的空括号去掉
所以可以简化为:

a { p1 , p2 ->
    p2 + p1
}

经过不断的简化,这就是我们日常最常见的形式了。
5.)当lambda表达式中只有一个参数,并且这个参数的类型能推导出来时,会生成默认参数名称it来代替这个参数,此时我们不需要显示的声明该参数的名称,也就是说可以省略掉
示例如下:

fun a(fb : (Int ) -> String) {

}
a{
    it.toString()
}

注意:当多个lambda嵌套的情况下,最好显式地声明每个lambda表达式的参数,否则很难搞清楚it引用的到底是什么值,严重影响代码可读性。
6.)在使用Lambda表达式的时候,可以用下划线(_)表示执行代码块中未使用的参数,表示不处理这个参数。

a { _ , p2 ->
    p2
}

二、SAM 转换

我们在上一篇中,也提到过Java传递函数的方法,使用接口,kotlin也提供了对接口的lambda语法,也就是SAM 转换:

  1. SAM转换只适用于接口,不适用于抽象类,即使这些抽象类也只有一个抽象方法。

  2. 必须是函数式接口,也就是使用fun interface 声明的接口,该接口只能有一个抽象方法(很显然,lambda表达式的最终目的就是想要一个动态的函数)
    SAM 转换就是将lambda显示转换为函数式接口实例而生成的函数

  3. 函数式接口和函数类型不是相同的东西,这很好理解,一个是接口一个是数据类型,不能混用

示例如下:我们定义一个函数式接口

fun interface Click {
    fun click(a : Int) : String
}
fun a(c : Click) {
    c.click(1)
}

在不使用lambda情况下,为了方便,我们一般使用对象表达式构建一个匿名内部类的对象传入

a(object : Click {
    override fun click(a : Int) : String {
        return a.toString()
    }
})

使用lambda,并且语法和上面提到的没有任何区别

a { a -> a.toString() }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值