函数类型
1.定义
Kotlin 使用类似 (Int) -> String 的一系列函数类型来处理函数的声明:
这些类型具有与函数签名相对应的特殊表示法,即它们的参数和返回值:
-
所有函数类型都有一个圆括号括起来的参数类型列表以及一个返回类型:
(A, B) -> C
表示接受类型分别为A
与B
两个参数并返回一个C
类型值的函数类型。 参数类型列表可以为空,如() -> A
。[Unit
返回类型]不可省略。 -
函数类型可以有一个额外的接收者类型,它在表示法中的点之前指定: 类型
A.(B) -> C
表示可以在A
的接收者对象上以一个B
类型参数来调用并返回一个C
类型值的函数。 [带有接收者的函数字面值]通常与这些类型一起使用。 -
[挂起函数]属于特殊种类的函数类型,它的表示法中有一个 suspend 修饰符 ,例如
suspend () -> Unit
或者suspend A.(B) -> C
。
函数类型表示法可以选择性地包含函数的参数名:(x: Int, y: Int) -> Point。 这些名称可用于表明参数的含义。
如需将函数类型指定为可空请使用圆括号:
((Int, Int) -> Int)?
。
函数类型可以使用圆括号进行接合:(Int) -> ((Int) -> Unit)
箭头表示法是右结合的,(Int) -> (Int) -> Unit
与前述示例等价,但不等于((Int) -> (Int)) -> Unit
。
2.函数类型实例化
有几种方法可以获得函数类型的实例:
使用函数字面值的代码块,采用以下形式之一:
- lambda 表达式:
{ a, b -> a + b }
, - 匿名函数:
fun(s: String): Int { return s.toIntOrNull() ?: 0 }
- 使用实现函数类型接口的自定义类的实例:
class IntTransformer: (Int) -> Int {
override operator fun invoke(x: Int): Int = TODO()
}
val intFunction: (Int) -> Int = IntTransformer()
如果有足够信息,编译器可以推断变量的函数类型:
val a = { i: Int -> i + 1 } // 推断出的类型是 (Int) -> Int
3.函数字面值
函数字面值是指不声明,而直接作为表达式传递的函数。它包括两种,lambda表达式及匿名函数。
3.1 lambda表达式
lambda表达式的全语法形式如下:
val sum: (Int, Int) -> Int = {x: Int, y: Int -> x + y}
其特点如下:
- lambda表达式必须在大括号中。
- lambda表达式的参数列表在->左边,参数类型是可选的,如果其类型可以推断出来,则类型可以省略。例如上例可简写为:
val sum = {x:Int, y:Int -> x + y}
3.2 匿名函数
lambda表达式不能显示的指定返回值的类型。如果需要显示指定返回值的类型,则需要使用匿名函数。匿名函数和普通函数非常类似,除了其函数名被省略。其示例如下:
fun(x: Int, y: Int): Int {
return x + y
}
请注意,匿名函数参数总是在括号内传递。 允许将函数留在圆括号外的简写语法仅适用于lambda表达式。
lambda表达式与匿名函数之间的另一个区别是非局部返回的行为。一个不带标签的return语句总是在用fun关键字声明的函数中返回。这意味着lambda表达式中的return将从包含它的函数返回,而匿名函数中的return将从匿名函数自身返回。