Kotlin 高阶函数与 lambda 表达式

Kotlin使用lambda 表达式促成

  • 可以在变量与数据结构中存储函数

  • 可以作为参数传递给其他高阶函数

  • 可以从其他高阶函数返回

  • 可以像操作任何其他非函数值一样对函数进行操作

1、高阶函数

将函数用作参数或返回值的函数,即高阶函数

高阶函数定义,只需要将参数类型或返回值类型中的任意一个定义为函数类型即可

Kotlin 复制代码
// 参数类型是函数类型
修饰符 函数名(参数名:(T...)-> R) : 返回值类型 {
    ...
    方法体
    ...
    return 返回值;
}
// 返回值类型是函数类型
修饰符 函数名(参数名:参数类型) : (T...)-> R {
    ...
    方法体
    ...
    return 返回值;
}
2、函数类型

格式: (T...)-> R (T、R均表示泛型) T...表示可以有多个形参,R也可以是Unit

分类:

  • () -> R, 表示无参,返回R类型的函数
Kotlin 复制代码
    // () -> R 类型函数声明和定义
    //lamba形式
    val aaa : () -> Int = {444}
    val bbb : () -> Unit = {println("Unit")}
    // 调用函数
    println(aaa())   //  444
    bbb()            //  Uint

    // 函数形式
    fun fun1(n: Int, lamba: () -> Int) : Unit {
        println("$n")            
        println("${lamba()}")  
    }
    // 调用函数
    fun1(111, aaa)
    /*
        111
        444
    */
  • (T) -> R, 表示一个T类型参数,返回R类型的函数
Kotlin 复制代码
    // (T) -> R 类型函数声明和定义
    val aaa : (String) -> Float = {
        println("$it")
        444.0f
    }
    // 调用函数
    println(aaa("hello")) 
    /*
       hello
       444.0
    */

    // 函数形式
    fun fun1(n: Int, lamba: (String) -> Float) : Unit {
        println("$n")            
        println("${lamba("word")}")  
    }
    // 调用函数
    fun1(111, aaa)
    /*
        222
        word
        444.0
    */
  • T.(A) -> R, 表示在 T 的接收者对象上用一个 A类型参数来调用,返回一个 R类型值的函数
Kotlin 复制代码
    // T.(A) -> R 类型函数声明和定义
    val aaa: String.(Int) -> Int = {
        // 传给调用的接收者对象成为隐式的this,
        // 以便访问接收者对象的成员而无需任何额外的限定符,
        // 亦可使用 this 表达式 访问接收者对象
        println("$this $it")
        555
    }
    // 调用函数
    println(aaa("hello", 444)) 
    /*
        hello 444
        555
    */

    // 函数形式
    fun fun1(n: Int, lamba: String.(Int) -> Int) : Unit {
        println("$n")            
        println("${lamba("word", 234)}")  
    }
    // 调用函数
    fun1(111, aaa)
    /*
        111
        word 234
        555
    */
  • (T, T.() -> R),表示接收输入一个T参数和一个代码块参数的函数
Kotlin 复制代码
    //接收(T, T.() -> R) 参数类型的函数声明和定义
	val aaa: (f: Float, s: String.(Int) -> Float) -> Int = {f, s ->
        println("$f")                      // 444.0
        var bb = s("hello", 444)
        println("$bb")                     // hello, 444
        555
    }
    // 调用函数
    var cc = aaa(444.0f){
        println("$this, $it")              // 333.0
        333.0f
    }
    println("$cc")                         // 555

    // 函数形式
    fun fun1(f: Float, s: String.(Int) -> Float) : Int {
        println("$f")                      // 111.0
        var dd = s("word", 234)
        println("$dd")                     // 222.0
        return 123
    }
    // 调用函数
    val ee = fun1(111f) {
        println("$this $it")               // word 234
        222.0f
    }
    println("$ee")                         // 123

函数的参数名可选:(x:Int,y: Int) -> Point;若返回Unit 类型不可省略,表示无返回值

使用圆括号,将函数类型指定为可空: ((Int, Int) -> Int)?

使用圆括号,进行接合:(Int) -> ((Int) -> Unit)

箭头表示法是右结合的:(Int) ->(Int)-> Unit 与前述示例等价,但不等于 ((Int) ->(Int))-> Unit

Kotlin 复制代码
class A
// 下面两个函数的调用方式都一样,都需要传入一个A对象,不同之处在函数体内
val myFun1 = fun A.() { // 在函数体内隐含this,可直接调用T成员变量和函数 }
val myFun2 = fun(a: A) { // 普通函数,必须使用a.的方式显式调用A类内的任意函数和变量 }
3、Lambda 表达式

lambda 表达式是函数字面值,即没有声明而是立即做为表达式传递的函数

语法:

  • lambda 表达式总是括在花括号中
  • 完整语法形式的参数声明放在花括号内,并有可选的类型标注
  • 函数体跟在一个 -> 之后。
  • 返回类型如果推断不是 Unit,则以 { } 里最后一个(或可能是单个)表达式会视为返回值
Kotlin 复制代码
// 完整形式
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }

// 简写形式
val sum = { x: Int, y: Int -> x + y }

拖尾 lambda 表达式:

Kotlin 复制代码
// 按照 Kotlin 惯例,如果函数的最后一个参数是函数
// 那么作为相应参数传入的 lambda 表达式可以放在圆括号之外
val product = items.fold(1) { acc, e -> acc * e }

// 如果该 lambda 表达式是调用时唯一的参数,那么圆括号可以完全省略
run { println("...") }

单个参数的隐式名称:it

Kotlin 复制代码
// 字面值是"(it: Int) -> Boolean"类型的
val aaa = { it > 0 }

限定返回语法:return@xxx 从 lambda 显式返回一个值,否则,将隐式返回最后一个表达式的值

Kotlin 复制代码
// 两个返回值是一样的
ints.filter {
    val shouldFilter = it > 0
    shouldFilter
}

ints.filter {
    val shouldFilter = it > 0
    return@filter shouldFilter
}

下划线:_ 接收变量

Kotlin 复制代码
// 参数1不使用,那么可以用下划线(_)取代其名称
map.forEach { (_, value) -> println("$value!") }
4、匿名函数

像常规函数一样声明,但省略其名称;当匿名函数作为参数传递时,需将其放在括号内;允许将函数留在圆括号外的简写语法仅适用于 lambda 表达式

Kotlin 复制代码
// lamba 形式
fun(x: Int, y: Int): Int = x + y

// 函数形式
fun(x: Int, y: Int): Int {
    return x + y
}
相关推荐
移动开发者1号4 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin
移动开发者1号4 小时前
构建高可用线上性能监控体系:从原理到实战
android·kotlin
恋猫de小郭14 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
androidwork16 小时前
深入解析内存抖动:定位与修复实战(Kotlin版)
android·kotlin
移动开发者1号21 小时前
ReLinker优化So库加载指南
android·kotlin
移动开发者1号1 天前
剖析 Systrace:定位 UI 线程阻塞的终极指南
android·kotlin
移动开发者1号1 天前
深入解析内存抖动:定位与修复实战(Kotlin版)
android·kotlin
Try0211 天前
Kotlin中Lambda表达式妙用:超越基础语法的力量
kotlin
泓博1 天前
KMP(Kotlin Multiplatform)改造(Android/iOS)老项目
android·ios·kotlin
移动开发者1号1 天前
使用Baseline Profile提升Android应用启动速度的终极指南
android·kotlin