Kotlin使用lambda 表达式促成

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

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

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

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

1、高阶函数

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

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

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

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

分类:

  • () ->R,表示无参返回R类型的函数

// () ->R 类型函数声明和定义//lamba形式val aaa : () -> Int = {444}val bbb : () -> Unit = {println("Unit")}// 调用函数println(aaa()) //444bbb()//Uint// 函数形式fun fun1(n: Int, lamba: () -> Int) : Unit {println("$n")println("${lamba()}")}// 调用函数fun1(111, aaa)/*111444*/
  • (T) -> R, 表示一个T类型参数返回R类型的函数

// (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)/*222word444.0*/
  • T.(A) -> R表示T的接收者对象上用一个 A类型参数来调用,返回一个R类型值的函数

// T.(A) ->R 类型函数声明和定义val aaa: String.(Int) -> Int = {// 传给调用的接收者对象成为隐式的this,// 以便访问接收者对象的成员而无需任何额外的限定符,// 亦可使用 this 表达式 访问接收者对象println("$this $it")555}// 调用函数println(aaa("hello", 444)) /*hello 444555*/// 函数形式fun fun1(n: Int, lamba: String.(Int) -> Int) : Unit {println("$n")println("${lamba("word", 234)}")}// 调用函数fun1(111, aaa)/*111word 234555*/
  • (T,T.() -> R),表示接收输入一个T参数一个代码块参数的函数
//接收(T,T.() -> R) 参数类型的函数声明和定义val aaa: (f: Float, s: String.(Int) -> Float) -> Int = {f, s ->println("$f")// 444.0var bb = s("hello", 444)println("$bb") // hello, 444555}// 调用函数var cc = aaa(444.0f){println("$this, $it")// 333.0333.0f}println("$cc") // 555// 函数形式fun fun1(f: Float, s: String.(Int) -> Float) : Int {println("$f")// 111.0var dd = s("word", 234)println("$dd") // 222.0return 123}// 调用函数val ee = fun1(111f) {println("$this $it") // word 234222.0f}println("$ee") // 123

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

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

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

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

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

3、Lambda 表达式

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

语法

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

拖尾 lambda 表达式:

// 按照 Kotlin 惯例,如果函数的最后一个参数是函数// 那么作为相应参数传入的 lambda 表达式可以放在圆括号之外val product = items.fold(1) { acc, e -> acc * e }// 如果该 lambda 表达式是调用时唯一的参数,那么圆括号可以完全省略run { println("...") }

单个参数的隐式名称:it

// 字面值是“(it: Int) -> Boolean”类型的val aaa = { it > 0 }

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

// 两个返回值是一样的ints.filter {val shouldFilter = it > 0shouldFilter}ints.filter {val shouldFilter = it > 0return@filter shouldFilter}

下划线:_ 接收变量

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

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

// lamba 形式fun(x: Int, y: Int): Int = x + y// 函数形式fun(x: Int, y: Int): Int {return x + y}