欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新

Kotlin 函数的默认参数没有出现在签名中 runBlocking 默认参数在源代码中未定义?默认参数的小坑,但是在Android

来源: 开发者 投稿于  被查看 40997 次 评论:214

Kotlin 函数的默认参数没有出现在签名中 runBlocking 默认参数在源代码中未定义?默认参数的小坑,但是在Android


问题起因

runBlocking的context参数有默认值。但是在Android Studio中查看源代码,发现源代码中定义如下:

  @Throws(InterruptedException::class)
  public actual fun <T> runBlocking(context: CoroutineContext, block: suspend CoroutineScope.() -> T): T

这就很奇怪了。因为doc中明明注释称context参数具有默认值,而且官方文档给出的签名如下:

expect fun <T> runBlocking(context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T

并且Kotlin在Github仓库上的源代码也确实与IDE中一致。
而且实际调试时可以发现确实传入了默认参数。那么到底是怎么回事呢?

真相

经过了反编译、查看文档与仓库多次对照后,终于发现问题所在:
问题的关键在于expectactual。初学者(比如我)可能会简单地不怎么注意函数签名的这一部分,然而正是这里造成了默认参数在源代码中令人困惑的现象!
由于expect定义处已经给出了默认参数,因此当调用到actual函数时,确实可以起到传入默认参数的作用。然而,令人十分困惑的是,在IDE中查找函数位置只能溯源到actual的函数而不是expect部分,因此很可能产生误解。
吃一堑长一智,以后再遇到类似地情况,请注意方法签名是否有actual!默认参数可能定义在expect部分中!另外,优先查看官方文档,IDE溯源代码可能产生误解。

用户评论