你不知道的Kotlin高阶函数应用

2022-02-08  本文已影响0人  寻水的鱼Chock
前言

函数,貌似好像存在于数学中的术语,突然感觉很陌生。

函数是定义在类中的一段独立的代码块,用来实现某个功能。函数又被称为方法。 函数在程序中使用很频繁,函数的主要目的是为了提高程序的复用性和可读性。

原来函数就是方法,平时使用“调用这个方法”、“这是**的方法”比较多,说回函数,反而有点陌生了。但是偶尔还是能看到的,比如“函数式编程”。

什么是高阶函数

高阶函数就是以另一个函数作为参数或返回值的函数,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

首先我们找出区别(除了参数和功能上的区别):

  1. 有suspend
  2. 括号前面有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()
    }
}

如果使用编辑器, 就更好理解了


image.png

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

上一篇 下一篇

猜你喜欢

热点阅读