Kotlin学习-函数(表达式,lambda,高阶函数)
Kotlin中函数 3种表达形式:
一般函数:
fun sum(a: Int, b: Int): Int { return a+b }
简化函数为表达式形式:
fun sum2(a: Int, b: Int): Int = a + b //函数表达式 fun max(a: Int, b: Int): Int = if(a > b) a else b //lambda函数 fun isOdd(x: Int) = x % 2 != 0
带默认参数的函数
//函数参数可以指定默认参数 fun multiply(a:Int,mut:Int=2):Int{ var result = 1 for(i in 0..mut){ result *= a } return result }
lambda表达式函数定义:
1. 无参数情况 :
val/var 变量名 = { ... }
2. 有参数情况
val/var 变量名 : (参数的类型,参数类型,...) -> 返回值类型 = {参数1,参数2,... -> 操作参数的代码 }
示例:val sumLambda: (Int, Int) -> Int = {x,y -> x+y}
注:(Int,Int)=>Int为函数签名,(a:Int,b:Int)表示函数参数
3,自动推导返回值类型(即表达式的返回值类型会根据代码实现块,推导出来)
val/var 变量名 = { 参数1 : 类型,参数2 : 类型, ... -> 操作参数的代码 }
示例:val sumLambda2 = {a : Int , b : Int -> a + b}
例如:
val sumLambda1: (Int, Int) -> Int = {x,y -> x+y} val sumLambda2 = {a : Int , b : Int -> a + b}
高阶函数:apply/run/also/let/with
kotlin标准库提供了Any对象上下文内执行一段代码块,可用于对象初始化,直接使用对象内部方法,使代码更精简化。
run即可作用于Any,又可作为this代码块,run返回执行的是处理结果
fun getIdentify(index:Int):String{ val person_play = run {//将最后处理结果返回 when(index){ 0 -> "manager" 1 -> "guest" 2 -> "worker" else -> "none" } } return person_play } fun getSampleNickName(nn:String):String{ var sampleName = nn.run { if(this.length>10) substring(0,this.length-6) else nn } return sampleName }
apply用法类似run,区别在于apply执行完成block()函数后,返回自身对象
返回自身对象,可以使用链式方法使用.apply{}.apply{}
val adam = Person("Adam").apply { age = 20 city = "London" }
fun testApply(st:String){
st.apply {
println("result:${this.plus("-java")}")
}.apply {
println("result:${this.plus("-php")}")
}
}
let内部使用it指代当前对象,返回最后一行处理结果, (T) -> R
fun testLet(st:String?){ st?.let { // execute this block if not nul it.plus("-let1") if(it.startsWith("android")) it.drop(8) } val listWithNulls: List<String?> = listOf("element1","element2", null) for (item in listWithNulls) { item?.let { // 元素不为空时执行 println(it) } } }
与let函数相似,区别是also执行完成后返回对象本身,let返回处理结果
fun testAlso() { val numberList = mutableListOf<Double>() numberList.also { println( "init the list") }.also { it.add( 2.71) it.add(3.14) it.add(1.0) }.also { println( "Sorting the list") }.sort() }
with函数作用于一个对象,返回最后一行处理结果
fun testWith(){ var p = Person("Tom", 26) //写法一,对象receiver和一个lambda函数块 val result = with(p, { println("my name is $name, I am $age years old") 1000 }) //由于with函数最后一个参数是一个函数,可以把函数提到圆括号的外部修改后 val result2 = with(p) { println("my name is $name, I am $age years old") 1000 } val numbers = mutableListOf("one" , "two","three") with(numbers) { val firstItem = first() val lastItem = last() println("First item: $firstItem, last item:$lastItem") } }
其它高阶函数
fun fooLabel1() { listOf(1, 2, 3, 4, 5).forEach(fun(value: Int) { if (value == 3) return // local return to the caller of the anonymous fun, i.e. the forEach loop print(value) }) print(" done with anonymous function") } fun fooLabel2() { listOf(1, 2, 3, 4, 5).forEach lit1@{ if (it == 3) return@lit1 // local return to the caller of the lambda, i.e. the forEach loop print(it) } print(" done with explicit label") } fun fooLabel3() {//implicit label listOf(1, 2, 3, 4, 5).forEach { if (it == 3) return@forEach // local return to the caller of the lambda, i.e. the forEach loop print(it) } print(" done with implicit label") } fun fooLabel5() { run loop@{ listOf(1, 2, 3, 4, 5).forEach { if (it == 3) return@loop // non-local return from the lambda passed to run print(it) } } print(" done with nested loop") }
函数作为参数
在kotlin中函数可以作为参数传递给另一个函数去执行
例1:
var globalLock = ReentrantLock() inline fun <T> lockInnerHandle(body: () -> T): T {//统一实现函数线程安全锁 globalLock.lock() try { return body() } finally { globalLock.unlock() } }
通过这种方式可以统一实现某些功能的形式,简化函数重复代码量,高阶函数 run/apply/let/also等也是将函数作为参数处理的
例2:
//function as param fun calFun(x:Int,y:Int,f:(Int,Int)->Int){ val result = f(x,y) println(result) } //simple call calFun(2,3,(a:Int,b:Int)=>{a*b})
函数引用
fun isOdd(x: Int) = x % 2 != 0 fun isOdd(s:String) = s =="kotlin"|| s =="java"|| s == "cpp" fun calLength(s:String ) = s.length val numbers = listOf(1,2,3) //normal invoke println(numbers.filter { isOdd(it) }) //Function References ::调用 println(numbers.filter(::isOdd)) //组合函数使用 fun composeFun(){ val oddLength = compose(::isOdd, ::calLength)//compose(f, g) = f(g(*)) val strings = listOf("a","ab" , "abc" ) println(strings.filter(oddLength)) } //组合函数定义 fun <A, B, C> compose(f: (B)-> C, g: (A) -> B): (A) -> C { return { x -> f(g(x)) } } //显示指定参数的方法,调用 val predicate: (String) -> Boolean = ::isOdd predicate("cpp") //调用类成员 class A(val p:Int) //调用类的成员方法或扩展方法 val prop = A::p