《Kotlin核心编程》 ——2.1.2 声明函数返回值类型

举报
华章计算机 发表于 2020/02/21 20:18:14 2020/02/21
【摘要】 本节书摘来自华章计算机《Kotlin核心编程》 —— 书中第2章,第2.1.2节,作者是水滴技术团队 。

2.1.2 声明函数返回值类型

虽然Kotlin在很大程度上支持了类型推导,但这并不意味着我们就可以不声明函数返回值类型了。先来看看Kotlin如何用fun关键字定义一个函数:

fun sum(x: Int, y: Int): Int { return x + y }

与声明变量一样,类型信息放在函数名的后面。现在我们把返回类型声明去掉试试:

>>> fun sum(x: Int, y: Int) { return x + y }

error: type mismatch: inferred type is Int but Unit was expected

在以上的例子中,因为没有声明返回值的类型,函数会默认被当成返回Unit类型,然而实际上返回的是Int,所以编译就会报错。这种情况下我们必须显式声明返回值类型。

由于一些语言如Java没有Unit类型,你可能不是很熟悉。不要紧,当前你可以暂时把它当作类似Java中的void。不过它们显然是不同的,Unit是一个类型,而void只是一个关键字,我们会在2.4.2节进一步比较两者。

也许你会说,Kotlin看起来并没有比Java强多少嘛,Java也支持某种程度上的类型推导,比如Java 7开始已经支持泛型上的类型推导,Java 10则进一步支持了“局部变量”的类型推导。

其实,Kotlin进一步增强了函数的语法,我们可以把{}去掉,用等号来定义一个函数。

fun sum(x: Int, y: Int) = x + y // 省略了{}

>>> sum(1, 2)

3

Kotlin支持这种用单行表达式与等号的语法来定义函数,叫作表达式函数体,作为区分,普通的函数声明则可叫作代码块函数体。如你所见,在使用表达式函数体的情况下我们可以不声明返回值类型,这进一步简化了语法。但别高兴得太早,再来一段递归程序试试看:

>>> fun foo(n: Int) = if (n == 0) 1 else n * foo(n - 1)

error: type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly

你可能觉察到了if在这里不同寻常的用法—没有return关键字。在Kotlin中,if是一个表达式,它的返回值类型是各个逻辑分支的相同类型或公共父类型。

表达式在Kotlin中占据了非常重要的地位,我们会在2.4节重点介绍这一特性。

我们发现,当前编译器并不能针对递归函数的情况推导类型。由于像Kotlin、Scala这类语言支持子类型和继承,这导致类型系统很难做到所谓的全局类型推导。

关于全局类型推导(global type inference),纯函数语言Haskell是一个典型的代表,它可以在以上的情况下依旧推导出类型。

所以,在一些诸如递归的复杂情况下,即使用表达式定义函数,我们也必须显式声明类型,才能让程序正常工作。

fun foo(n: Int): Int = if (n == 0) 1 else n * foo(n - 1) // 需显式声明返回类型

>>> foo(2)

2

此外,如果这是一个表达式定义的接口方法,显式声明类型虽然不是必需的,但可以在很大程度上提升代码的可读性。

总结

我们可以根据以下问题的提示,来判断是否需要显式声明类型:

如果它是一个函数的参数?

   必须使用。

如果它是一个非表达式定义的函数?

   除了返回Unit,其他情况必须使用。

如果它是一个递归的函数?

   必须使用。

如果它是一个公有方法的返回值?

为了更好的代码可读性及输出类型的可控性,建议使用。

除上述情况之外,你可以尽量尝试不显式声明类型,直到你遇到下一个特殊情况。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。