你不知道的Kotlin高阶函数应用
前言
函数,貌似好像存在于数学中的术语,突然感觉很陌生。
函数是定义在类中的一段独立的代码块,用来实现某个功能。函数又被称为方法。 函数在程序中使用很频繁,函数的主要目的是为了提高程序的复用性和可读性。
原来函数就是方法,平时使用“调用这个方法”、“这是**的方法”比较多,说回函数,反而有点陌生了。但是偶尔还是能看到的,比如“函数式编程”。
什么是高阶函数
高阶函数就是以另一个函数作为参数或返回值的函数,Kotlin可以以lambda或参数引用作为参数或返回值。
所以,任何以lambda或函数引用作为参数或返回值的都是高阶函数。
原来是TA:
var sum: (Int, Int) -> Int = {x , y-> x + y}
对高阶函数不熟悉的同学可以参考这两篇博文,写的非常好。
Kotlin-高阶函数的使用(一)
Kotlin-高阶函数的使用(二)
发现问题
有使用协程经验的同学看到这个可能会有疑问,还能这样?第一反应表示--看不懂啊。
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
val newContext = newCoroutineContext(context)
val coroutine = if (start.isLazy)
LazyStandaloneCoroutine(newContext, block) else
StandaloneCoroutine(newContext, active = true)
coroutine.start(start, coroutine, block)
return coroutine
}
context和start参数好理解,就是一个带默认参数的入参定义,最后一个block就是今天要讨论的高阶函数。
我们把它摘出来:
block: suspend CoroutineScope.() -> Unit
平时我们使用比较多的大抵是如下的几种
block: () -> Unit
block: (x: Int) -> Unit
block: (x: Int) -> Int
首先我们找出区别(除了参数和功能上的区别):
- 有suspend
- 括号前面有CoroutineScope.
??????还能这样? 似乎没学过啊, 也没人教我啊,细思极恐。
所以平时阅读源码的优势就体现出来了,不仅能查缺补漏,还能“打开新世界的大门”
解决问题
1、suspend
suspend是协程中的关键字,中文意思就是「暂停」或者「可挂起」的意思
协程运行时的挂起就是通过suspend来实现的。学习协程相关知识点这里
这个好理解,就是这个block只能使用协程的方式进行调用。
2、CoroutineScope.
这个就有意思了。
你看到的CoroutineScope.()其实是具体的具象, 它可以是任何对象。比如
fun setBlock(block: View.() -> Unit) {}
还可以是泛型
fun <T> setBlock(block: T.() -> Unit) {}
block: T.() -> Unit 表示用这个T.()类型的方法作为setBlock方法的参数去表示一个不需要返回值的函数
为什么不是() -> Unit?
下面的例子将展示T.() -> Unit跟() -> Unit的区别
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val view: TextView = findViewById(R.id.tv)
view.setBlock {
Log.i("@@", "setBlock -> ${this::class.java.simpleName}")
//setBlock -> TextView
}
view.setBlock2 {
Log.i("@@", "setBlock2 -> ${this::class.java.simpleName}")
//setBlock2 -> MainActivity
}
}
fun <T : View> T.setBlock(f: T.() -> Unit) {
f()
}
fun <T : View> T.setBlock2(f: () -> Unit) {
f()
}
}
如果使用编辑器, 就更好理解了

所以,T.() -> Unit跟() -> Unit的区别就是影响、控制block执行的作用域。