函数
在 Kotlin 中, 你可以使用 fun
关键字声明你自己的函数.
在 Kotlin 中:
函数参数写在小括号
()
之内.每个参数必须指定类型, 多个参数必须用逗号
,
隔开.返回值类型写在函数的小括号
()
之后, 用冒号:
隔开.函数的 body 部写在大括号
{}
之内.return
关键字用来退出函数, 或从函数返回某个值.
在下面的示例中:
x
和y
是函数参数.x
和y
类型为Int
.函数的返回值类型为
Int
.函数被调用时返回
x
和y
的和.
命名参数
为了让代码更简洁, 调用函数时, 你不必指定参数名称. 但是, 指定参数名称可以让你的代码更易于阅读. 这种方式称为 命名参数(named argument). 如果你指定了参数名称, 那么可以用任意的顺序来写这些参数.
默认的参数值
你可以为函数参数定义默认值. 调用你的函数时, 有默认值的参数可以省略. 要声明默认值, 请在参数类型之后使用赋值操作符 =
:
没有返回值的函数
如果你的函数不返回任何有用的值, 那么它的返回值类型为 Unit
. Unit
类型只有唯一的一个值 – Unit
. 你不必在你的函数 body 部明确的声明返回值为 Unit
. 因此你不必使用 return
关键字, 也不必声明返回值类型:
单一表达式函数
为了让代码更加简洁, 你可以使用单一表达式函数. 例如, sum()
函数可以写得更短一些:
你可以删除大括号 {}
, 使用赋值操作符 =
来声明函数的 body 部. 由于 Kotlin 的类型推断能力, 你还可以省略返回值类型. 这样, sum()
函数就变成只有 1 行:
函数的实际练习
习题 1
写一个名为 circleArea
的函数, 接受一个整数参数, 表示圆的半径, 输出圆的面积大小.
习题 2
将前一个习题中的 circleArea
函数重写为单一表达式函数.
习题 3
你有一个函数, 它接受一个时/分/秒单位给定的时间间隔, 然后翻译为秒单位. 大多数情况下, 你只需要传递 1 个或 2 个参数, 而其它参数为 0. 改进这个函数以及调用它的代码, 使用默认参数值和命名参数, 让代码更加易于阅读.
Lambda 表达式
Kotlin 允许你使用 Lambda 表达式, 为函数编写更加简洁的代码.
例如, 下面的 uppercaseString()
函数:
可以写成一个 Lambda 表达式:
Lambda 表达式初看起来可能难于理解, 所以我们将它分解成各个部分. Lambda 表达式写在大括号 {}
之内.
在 Lambda 表达式之内, 你会写以下内容:
参数, 在
->
之前.函数 body 部, 在
->
之后.
在上面的示例中:
string
是函数参数.string
类型为String
.函数返回对
string
调用.uppercase()
函数的结果.
可以用很多方式使用 Lambda 表达式. 你可以:
赋值给变量
要将 Lambda 表达式赋值给一个变量, 请使用赋值操作符 =
:
传递给另一个函数
将 Lambda 表达式传递给另一个函数, 这个功能是很有用的, 一个很好的例子是对集合(Collection)使用 .filter()
函数:
.filter()
函数接受一个 Lambda 表达式, 作为判定条件:
{ x -> x > 0 }
接受 List 中的每个元素, 只返回正数.{ x -> x < 0 }
接受 List 中的每个元素, 只返回负数.
另一个好的例子是, 使用 .map()
函数, 对集合中的元素进行变换:
.map()
函数接受一个 Lambda 表达式, 作为变换函数:
{ x -> x * 2 }
接受 List 中的每个元素, 返回这个元素乘以 2 的结果.{ x -> x * 3 }
接受 List 中的每个元素, 返回这个元素乘以 3 的结果.
函数类型
在从一个函数返回一个 Lambda 表达式之前, 你首先需要理解 函数类型.
你已经学习了基本类型, 但函数本身也有它的类型. Kotlin 的类型推断功能能够通过参数类型推断一个函数的类型. 但有的时候你需要明确指定函数类型. 编译器需要函数类型, 然后才能知道对这个函数允许什么, 不允许什么.
函数类型的语法包括:
每个参数的类型, 写在小括号
()
之内, 以逗号,
分隔.返回值类型, 写在
->
之后.
例如: (String) -> String
, 或 (Int, Int) -> Int
.
如果为 upperCaseString()
定义一个函数类型, 那么 Lambda 表达式如下:
如果你的 Lambda 表达式没有参数, 那么小括号 ()
保留为空. 例如: () -> Unit
从函数中返回
可以从函数中返回 Lambda 表达式. 为了让编译器知道返回的 Lambda 表达式 的类型, 你必须声明一个函数类型.
在下面的示例中, toSeconds()
函数返回的函数类型是 (Int) -> Int
, 因为它总是返回一个 Lambda 表达式, 这个 Lambda 表达式接受一个 Int
类型的参数, 并返回一个 Int
值.
这个示例使用 when
表达式, 来确定在调用 toSeconds()
时返回哪个 Lambda 表达式:
单独调用
Lambda 表达式可以单独调用, 方法是在大括号 {}
之后添加小括号 ()
, 并在小括号中加上参数:
尾缀 Lambda 表达式(Trailing Lambda)
你已经看到, 如果一个 Lambda 表达式是函数的唯一参数, 你可以去掉函数的小括号 ()
. 如果一个 Lambda 表达式是函数的最后一个参数, 那么 Lambda 表达式可以写在函数的小括号 ()
之外. 对这两种情况, 这样的语法称为 尾缀 Lambda 表达式(Trailing Lambda).
例如, .fold()
函数接受一个初始值, 以及一个操作:
关于 Lambda 表达式, 更多详情请参见 Lambda 表达式与匿名函数(Anonymous Function).
本教程的下一章是学习 Kotlin 中的 类.
Lambda 表达式的实际练习
习题 1
你有一个 Web Service 支持的动作列表, 所有请求的一个共通前缀, 某个资源的一个 ID. 要对资源 ID 5 请求 title
动作, 你需要创建下面的 URL: https://example.com/book-info/5/title
. 使用一个 Lambda 表达式, 从动作列表创建对应的 URL 列表.
习题 2
编写一个函数, 接受一个 Int
值和一个动作 (一个 () -> Unit
类型的函数), 然后重复执行这个动作指定的次数. 然后使用这个函数打印 “Hello” 5 次.