有趣的 Kotlin 0x08:What am I

最近在 http://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 实现

引用官方图片说明问题:https://kotlinlang.org/docs/mobile/connect-to-platform-specific-apis.html

Expect/actual declarations in common and platform-specific modules

Expect/actual declarations for getting the UUID

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AndroidKt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值