Kotlin的高阶函数
一、高阶函数介绍
在Kotlin中,高阶函数即指:将函数用作一个函数的参数或者返回值的函数。
1.1、将函数用作函数参数的情况的高阶函数
// sumBy函数的源码 public inline fun CharSequence.sumBy(selector: (Char) -> Int): Int { var sum: Int = 0 for (element in this) { sum += selector(element) } return sum }
所以这个函数的作用是:把字符串中的每一个字符转换为Int的值,用于累加,最后返回累加的值
val testStr = "abc" val sum = testStr.sumBy { it.toInt() } println(sum)
1.2、将函数用作一个函数的返回值的高阶函数
fun <T> lock(lock: Lock, body: () -> T): T { lock.lock() try { return body() } finally { lock.unlock() } }
1.3、高阶函数的使用
在上面的两个例子中,我们出现了str.sumBy{ it.toInt }这样的写法。其实这样的写法在前一章节Lambda使用中已经讲解过了。这里主要讲高阶函数中对Lambda语法的简写。
从上面的例子我们的写法应该是这样的:
str.sumBy( { it.toInt } )
但是根据
Kotlin中的约定,即当函数中只有一个函数作为参数,并且您使用了lambda表达式作为相应的参数,则可以省略函数的小括号()。故而我们可以写成:
str.sumBy{ it.toInt }
还有一个约定,即当函数的最后一个参数是一个函数,并且你传递一个lambda表达式作为相应的参数,则可以在圆括号之外指定它。故而上面例2中的代码我们可写成:
str.sumBy{ it.toInt }
二、自定义高阶函数
private fun resultByOpt(num1 : Int , num2 : Int , result : (Int ,Int) -> Int) : Int{ return result(num1,num2) } fun main() { val result1 = resultByOpt(1,2){ num1, num2 -> num1 + num2 } val result2 = resultByOpt(3,4){ num1, num2 -> num1 - num2 } val result3 = resultByOpt(5,6){ num1, num2 -> num1 * num2 } val result4 = resultByOpt(6,3){ num1, num2 -> num1 / num2 } println("result1 = $result1") println("result2 = $result2") println("result3 = $result3") println("result4 = $result4") }
三、常用的标准高阶函数介绍
1、T.apply()函数
public inline fun <T> T.apply(block: T.() -> Unit): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() return this }
T.apply执行完了block()函数后,返回了自身对象。
block()这个函数参数是一个扩展在T类型下的函数。这说明我的block()函数可以可以使用当前对象的上下文。所以当我们传入的lambda表达式想要使用当前对象的上下文的时候,我们可以使用这个函数。
val mTvBtn = findViewById<TextView>(R.id.text) mTvBtn.apply{ text = "kotlin" textSize = 13f ... }.apply{ // 这里可以继续去设置属性或一些TextView的其他一些操作 }.apply{ setOnClickListener{ .... } }
2、T.also()函数
public inline fun <T> T.also(block: (T) -> Unit): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block(this) return this }
从上面的源码在结合T.apply函数的源码我们可以看出: T.also函数中的参数block函数传入了自身对象。故而这个函数的作用是用用block函数调用自身对象,最后在返回自身对象
这里举例一个简单的例子,并用实例说明其和T.apply的区别
例:
"kotlin".also { println("结果:${it.plus("-java")}") }.also { println("结果:${it.plus("-php")}") } "kotlin".apply { println("结果:${this.plus("-java")}") }.apply { println("结果:${this.plus("-php")}") }
他们的输出结果是相同的:
结果:kotlin-java 结果:kotlin-php 结果:kotlin-java 结果:kotlin-php
3、T.let()函数
public inline fun <T, R> T.let(block: (T) > R): R { contract {callsInPlace(block, InvocationKind.EXACTLY_ONCE) } return block(this) }
"kotlin".let { println("原字符串:$it") it.reversed() }.let { println("反转字符串后的值:$it") it.plus("-java") }.let { println("新的字符串:$it") } "kotlin".also { println("原字符串:$it") it.reversed() }.also { println("反转字符串后的值:$it") it.plus("-java") }.also { println("新的字符串:$it") } "kotlin".apply { println("原字符串:$this") this.reversed() }.apply { println("反转字符串后的值:$this") this.plus("-java") }.apply { println("新的字符串:$this") }
原字符串:kotlin 反转字符串后的值:niltok 新的字符串:niltok-java 原字符串:kotlin 反转字符串后的值:kotlin 新的字符串:kotlin 原字符串:kotlin 反转字符串后的值:kotlin 新的字符串:kotlin