美文网首页禅与计算机程序设计艺术简书人物Kotlin专题
Kotlin学习之高阶函数和Lambda表达式:函数类型和匿名函

Kotlin学习之高阶函数和Lambda表达式:函数类型和匿名函

作者: 程序员丶星霖 | 来源:发表于2017-12-21 09:04 被阅读48次

Kotlin学习之高阶函数和Lambda表达式:函数类型和匿名函数

高阶函数是参数或返回值包含函数的函数,Lamdba表达式可以视为立即执行的匿名函数。通常不会定义一个Lambda函数,而是把Lambda表达式作为另一个函数的参数,能够接受Lombda表达式作为参数的函数就是一个高阶函数。所以说,高阶函数是Lambda表达式的基础。

函数有如下四个属性,哪些属性时必须的,哪些又不是?

  • 名称:可以没有,如果一个行为只是一次性的,不会再用到,就可以没有名字。
  • 参数列表:一定要有。参数列表是函数的入口,它描述了一个函数能接受什么样的“材料”,一个Int、两个String或不需要参数,都应该明确指定,否则就会出现严重的错误。
  • 返回值类型:一定要有。程序是由一个又一个函数组合起来的,一个函数的出口就是另一个函数的入口,如果不知道一个函数会“产出”什么样的结果,就不可能把它们组合起来。
  • 函数体: 可以没有。抽象方法就是没有方法体的函数,它只定义了行为,没有定义实现。

也就是说,参数列表和返回值类型是一个函数不可或缺的属性,我们在描述一个函数对象时,首先要指明的就是参数列表和返回值类型。

一、Kotlin函数类型

Kotlin使用类似Lambda表达式的形式来表示一个函数的类型:

(参数列表类型) -> 返回值类型

如下:

val sum: (Int, Int) -> Int

定义了一个名称为sum,参数列表为两个Int类型,返回值为Int类型的函数。

我们没有定义函数体,相当于没有初始化这个变量,这时需要给它赋一个函数体的值,才能够调用它实现功能。这就需要用匿名函数了。

二、Kotlin匿名函数

所谓匿名函数,就是没有名称的函数,只定义了参数列表、返回值类型和函数体。
把一个匿名函数赋给一个没有定义函数体的函数对象,就构成了一个完整的函数。

Kotlin中这样定义一个匿名函数:

fun(参数列表): 返回值类型 {
  函数体
}

当函数体只有一句,且可以推断出返回值类型时,可以如下这样写:

fun(参数列表) = 函数体

为了和上面定义的sum函数对象的参数列表和返回值类型匹配,我们可以定义一个匿名函数,然后把它赋值给sum变量:

val sum: (Int, Int) -> Int = fun(a: Int, b: Int) = a + b

由于匿名函数已经定义好参数列表和返回值类型了,我们可以省略sum的类型声明:

val sum = fun(a: Int, b: Int) = a + b

Lambda表达式就是一个匿名函数,可以把这个匿名函数改写为Lambda表达式:

val sum = { a: Int, b: Int -> a + b }

三、Function接口

函数只有一个方法:调用。它包含三个动作:传入参数、处理参数、返回结果。

Kotlin定义了kotlin.Function<out R>接口来抽象所有函数,它没有定义任何方法。关键在于:kotlin.jvm.functions包里定义了Function0<out R>到Function22<out R>来分别抽象无参到22个参数的函数,它们都继承了kotlin.Function接口,同时定义了一个invoke()函数。

如下是Function2接口:

interface Function2<in P1, in P2, out R> : Function<R> {
  operator fun invoke(p1: P1, p2: P2): R
}

p1和p2是传入的两个参数类型,R就是返回值类型。因为我们只会向函数传入参数、从函数中取出返回值,所以分别用in和out修饰。

invoke()函数定义了“调用”这个行为,它同时重载了括号操作符,允许用括号来传入参数、得到返回值。

上面定义的sum函数对象,它会被编译为一个Function2类型的对象,(Int,Int)->Int是Function2接口的具体实现类,可以使用invoke()函数来调用它:

println(sum.invoke(1,2))

也可以直接用括号操作符:

println(sum(1,2))

学海无涯苦作舟

我的微信公众号.jpg

相关文章

网友评论

    本文标题:Kotlin学习之高阶函数和Lambda表达式:函数类型和匿名函

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