但是当你需要定义参数的时候,或者不止一个参数要定义的时候,语法就是这样的: { x, y -> x + y }。我们可以创建一段代码,一个函数表达式,输入两个参数,然后把它们相加。如果我们愿意,我们可以显示定义类型。
[代码]csharp代码:
1
2
3
4
5
{ x, y -> x + y }
val sum: (Int, Int) -> Int = { x, y -> x + y }
val sum = { x: Int, y: Int -> x + y }
然后,在 fields 上存储它们。现在你可以看到在前二个例子中,类型是在 field 本上上定义的。这意味着函数表达式不需要任何类型信息。然后往下一个,类型信息在函数表达式里面自己包含了,所以我们不需要在变量定义时加入类型信息。
在最后一个例子中,返回值是推断出来的。两个整型相加,输出只能是整型。所以你不需要显示定义它们。
Higher-order 函数
这是个新奇的术语,它指的是函数可以接收函数,或者函数可以返回函数。这里是个例子
[代码]csharp代码:
1
2
3
4
5
6
func apply(one: Int, two: Int, func: (Int, Int) -> Int): Int {
return func(one, two)
}
val sum = apply(1, 2, { x, y -> x + y })
val difference = apply(1, 2, { x, y -> x - y })
这里我们定义一个函数,接收两个整型作为参数。然后第三个参数是一个函数。这和我们之前看到的语法一样,那里我们定义了一个函数接收两个整型并返回一个整型。
然后,在函数体内部,我们调用了该函数,并且传入了两个参数。这就是我们如何使用它来计算和或者其他的东西的方法。我们把这段代码应用到了这两个数字上。回到之前所说的地方,我们说这段代码知道如何相加或者相减,而且我们把它运用到我们传入这个方法的数据上。然后这段代码在自己合适的上下文环境中自动运行。
Kotlin 给你提供了一个手动的方式来调整这段代码成为更好的语法表达。如果函数的最后一个参数是个表达式,你一直都不需要使用括号,你可以只用在所有参数初始化后添加一个。
[代码]csharp代码:
1
2
val sum = apply(1, 2) { x, y -> x + y }
val difference = apply(1, 2) { x, y -> x - y }
这项技术允许你创建非常漂亮的 DSL 和 API。你可以像 Int 的扩展一样来编写它们。
包含 higher-order 函数的应用
[代码]csharp代码:
01
02
03
04
05
06
07
08
09
10
11
12
fun <t> List<t>.filter(predicate: (T) -> Boolean): List<t> {
val newList = ArrayList<t>()
for (item in this) {
if (predicate(item)) {
newList.add(item)
}
}
return newList
}
val names = listOf("Jake", "Jesse", "Matt", "Alec")
val jakes = names.filter { it == "Jake" }</t></t></t></t>
一个常见的操作是你有一个事情的列表,然后你需要基于一些条件来过滤它们。因为我们有 extension methods 和 higher-order functions,我们可以在列表上写一个这样的函数。这和你期望的实现一样,这个函数比较每个列表中的元素然后返回正确的结果。
现在如果你有一个包含数据的列表,只需用一行代码,如此简洁的函数就能过滤出我们想要的数据。谢天谢地,这个功能实际上已经在 Kotlin 标准库里面包含了,这样我们就不用扩展列表类了。
大部分 Kotlin 的库都已经实现了现有的 Java 类型中类似的高级函数来,这样可以统一在这些类型上的操作。
看看这个在 Kotlin 标准库里面不存在的应用:
[代码]csharp代码:
1
2
3
4
5
fun Any.lock(func: () -> Unit) {
synchronized (this) {
func()
}
}