前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >让你迷惑的 Kotlin 代码(2)

让你迷惑的 Kotlin 代码(2)

作者头像
路遥TM
发布2021-08-31 15:42:53
2720
发布2021-08-31 15:42:53
举报
文章被收录于专栏:路遥的专栏

今天的问题格外短,也格外简单。

代码语言:javascript
复制
fun hello() = {
    println("Hello World !")
}

fun main() {
    hello()
}

暂且不纠结答案,先来回顾一下 Kotlin 中是如何声明函数的。

Kotlin 使用 fun 关键字来声明函数,如下所示:

代码语言:javascript
复制
fun hello() = "Hello World"

Kotlin 会自动推导函数返回值,上面的代码定义了一个返回值是 String 的函数。

那么...... 下面的代码正确吗?

代码语言:javascript
复制
fun hello2() {
    return "Hello World"
}

hello2() 是不能正常编译的。因为如果显式使用了 return,也必须显式指定返回值类型。

到这,注意两个点:

  • Kotlin 会自动推导函数返回值类型,但显式 return 也必须显式声明返回值类型
  • 使用 = 定义函数可以省略函数返回值类型

回到题目中的代码:

代码语言:javascript
复制
fun hello() = {
    println("Hello World !")
}

这就很明了了,声明了一个返回值类型可自动推导的函数 hello() ,其返回值类型就是 = 后面的 {...}

这个大括号是什么类型呢?熟悉 Kotlin 语法的同学应该知道,{} 是 Lambda 表达式。

Lambda 又是什么类型呢?Kotlin 中的 Lambda 是函数类型的对象。

在 Kotlin 中,函数也是对象,但又不是传统意义上的对象。每个函数对象都有自己的函数类型,这个类型又有很多种,由函数的参数类型和返回值类型共同决定。要注意一点,Lambda 表达式的最后一行就是其返回值。

代码语言:javascript
复制
val a: () -> Unit = { }
val b: (Int) -> String = { i -> "" }
val c: (Int, String) -> Int = { i, s -> 1 }
val d: (Int) -> ((Int) -> Unit) = { i -> {} }

上图的 a、b、c、d 是四个具有不同函数类型的函数对象。其中 d 是一个参数是 Int , 返回值类型是函数类型 (Int) -> Unit的函数对象。

再看下面四行代码:

代码语言:javascript
复制
val a = { }
val b = { i -> "" }
val c = { i, s -> 1 }
val d = { i -> {} }

哪几个会编译失败?

b、c、d 。虽然 Lambda 表达式可以自动推导函数的参数类型,但 b、c、d 显然超出能力范围以外。

最后回到开头的题目:

代码语言:javascript
复制
fun hello() = {
    println("Hello World !")
}

很清晰明了了。hello 函数返回了一个 Lambda ,其函数类型是 () -> Unit 。对于返回值或者参数是函数类型的函数,我们也叫 高阶函数 。上面的代码其实等价于如下代码:

代码语言:javascript
复制
fun hello(): () -> Unit {
    return { println("Hello World !") }
}

所以,执行 hello() 只是获取了一个函数类型的对象,不会发生任何事。要真正的打印出 Hello World !,得使用 hello()() 或者 hello().invoke()

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 路遥TM 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档