有趣的 Kotlin 0x01:Scala-like functions

896 阅读2分钟

这是我参与更文挑战的第 29 天,活动详情查看: 更文挑战

最近在 portal.kotlin-academy.com/#/ 上看到很多关于 Kotlin 的有趣的题目。个人觉得很适合 Kotlin 爱好者,感兴趣的小伙伴可自行查阅。 【有趣的 Kotlin 】系列记录自己对每一题的理解。

0x01:Scala-like functions

fun hello() = {
    println("Hello, World")
}

fun main(args: Array<String>) {
    hello()
}

以上代码,运行结果为何?可选项:

  1. Does not compile
  2. Prints "Hello, World"
  3. Nothing
  4. Something else

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

分析

其实问题主要集中在 hello() 函数的理解上,题中:

fun hello() = {
    println("Hello, World")
}

而我们常见的函数的写法是这样的:

fun hello() {
    println("Hello, World")
}

两者相比,题中多出来一个 = 号,这就让两个函数有了本质上的差异。 先看下我们常见的不带等号的写法:

fun hello() {
    println("Hello, World")
}
  • 函数名:hello
  • 函数参数:无
  • 返回值:Unit

再看带等号的题中的写法:

fun hello() = {
    println("Hello, World")
}
  • 函数名:hello
  • 函数参数:无
  • 返回值:???

这个函数的返回类型是啥 ?我们先看一个例子:

fun isPositive(number: Int) =  number > 0

同样是 =,但是后面跟的内容不一样, number > 0 是一个表达式,由于根据表达式可以推断出返回类型,这里就省略了返回值 Boolean

对比上面题中 hello 函数的写法,其实也是一种省略了返回值类型的简略写法。先看等号后跟的内容

= {
    println("Hello, World")
}

其实就是一个 Lambda 表达式,而 Lambda 表达式是函数类型实例化的一种方式,所以 hello 函数的返回值是一个函数类型,且函数类型为 () \rightarrow Unit。这样答案就很明显了。我们把返回类型补全后,题目内容变为:

fun hello(): () -> Unit = {
    println("Hello, World")
}

fun main(args: Array<String>) {
    hello()
}

main 函数中调用 hello 函数只是返回一个函数类型实例,并没有调用这个函数类型实例,所以 “Hello, World” 是不会打印的。那么,正确答案为:3. Nothing

倘若我们想打印 “Hello, World” 该如何修改呢?三种方式:

  • 第一种:去掉 hello 函数定义中的等号
fun hello() {    println("Hello, World")}fun main(args: Array<String>) {    hello()}
  • 第二种:通过操作符 () 调用函数类型实例
fun hello() = {    println("Hello, World")}fun main(args: Array<String>) {    hello()()}
  • 第三种:通过操作符 invoke 调用函数类型实例
fun hello() = {    println("Hello, World")}fun main(args: Array<String>) {    hello().invoke()}