阅读 284

有趣的 Kotlin 0x08:What am I

最近在 portal.kotlin-academy.com/#/ 上看到很多关于 Kotlin 的有趣的题目。个人觉得很适合 Kotlin 爱好者,感兴趣的小伙伴可自行查阅。

【有趣的 Kotlin 】系列记录自己对每一题的理解。

0x08:What am I ?

fun main(args: Array<String>) {
    val whatAmI = {}()
    println(whatAmI)
}
复制代码

以上代码,运行结果是什么?可选项:

  1. "null"
  2. "kotlin.Unit"
  3. Doesn't print anything
  4. Doesn't compile

思考一下,记录下你心中的答案。

分析

不知不觉已经到第八题了,每看一题,感觉自己还是有收获的,并且每道题背后的知识点都可以在官方文档内找到依据,做题的同时也倒逼自己去反复阅读官方文档。

如果前面七题都认真看过的朋友应该能很快得出这一题的答案:

选项 2 :"kotlin.Unit"

有疑问的朋友继续往下,若聪明的你已经得到正确答案,请自由活动。

这一题只要明确变量 whatAmI 的类型,问题就迎刃而解了。

我们把大括弧和小括号分开看,只留下大括弧的 whatAmI 是什么类型 ?

val whatAmI = {}
复制代码

等号右侧是一个 Lambda 表达式,类型为 ()-> Unit ,即变量 wahtAmI 的类型,而 Lambda 表达式后跟上 () 其实就是调用 invoke() 函数,表示函数类型的调用。

那么,一个类型为 ()-> Unit 的函数类型调用后返回什么呢?自然是 Unit , 我是不是说了一句废话。所以 ,题中

val whatAmI = {}()
复制代码

wahtAmI 的类型为 kotlin.Unit,所以答案就是 kotlin.Unit ? 不够严谨。我们还需要再看看 println 函数在 JVM 平台上的实现逻辑,虽然内容可能很简单

/** Prints the given [message] and the line separator to the standard output stream. */
@kotlin.internal.InlineOnly
public actual inline fun println(message: Any?) {
    System.out.println(message)
}
复制代码

继续往下

public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {
        print(s);
        newLine();
    }
}
复制代码

再到 valueOf() 方法

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}
复制代码

所以,题目最后输出到控制台的内容取决于 kotlin.UnittoString() 方法。

public object Unit {
    override fun toString() = "kotlin.Unit"
}
复制代码

此时,我们才能说本题的正确答案是:

选项 2 :"kotlin.Unit"

延伸

我们查看 println() 函数实现时有如下代码

/** Prints the given [message] and the line separator to the standard output stream. */
@kotlin.internal.InlineOnly
public actual inline fun println(message: Any?) {
    System.out.println(message)
}
复制代码

出现一个 actual 关键字,可能有些读者不太清楚,稍作解释。

Kotlin 语言从设计初期开始,定位就是跨平台语言,旨在让开发者使用 Kotlin 语言开发任意平台的应用。但是在某些情况下开发者可能需要针对不同的平台编写不同的代码。 这时我们需要通过 expect 关键字在公共代码部分定义需要在不同平台实现的类或者方法,然后在各平台对应的目录下通过 actual关键字去实现对应的类或方法,这便是 Kotlin 的 expect/actual 机制。那我们来找一找 println() 对应的 expect 函数。

Where is my expect ?

found my expect

采用类似的方法,我们也能寻得其他平台的 println() 实现

其他平台 println 实现

引用官方图片说明问题:kotlinlang.org/docs/mobile…

Expect/actual declarations in common and platform-specific modules

Expect/actual declarations for getting the UUID

文章分类
Android
文章标签