函数
默认参数
函数参数可以有默认值,当省略相应的参数时使用默认值。与其他语言相比,这可以减少重载数量。
fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) {
……
}
如果一个默认参数在一个无默认值的参数之前,那么该默认值只能通过使用命名参数调用该函数来使用:
fun foo(bar: Int = 0, baz: Int) { /* …… */ }
foo(baz = 1) // 使用默认值 bar = 0
不过如果最后一个 lambda 表达式参数从括号外传给函数函数调用,那么允许默认参数不传值:
fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { /* …… */ }
foo(1) { println("hello") } // 使用默认值 baz = 1
foo { println("hello") } // 使用两个默认值 bar = 0 与 baz = 1
单表达式函数
当函数返回单个表达式时,可以省略花括号并且在=符号之后指定代码体即可
fun double(x: Int): Int = x * 2
可变数量的参数(Varargs)
函数的参数可以用vararg
修饰符标记
fun <T> asList(vararg ts: T): List<T> {
val result = ArrayList<T>()
for (t in ts) // ts is an Array
result.add(t)
return result
}
//允许将可变数量的参数传递给函数
val list = asList(1, 2, 3)
中缀表示法
- 他们是成员函数或扩展函数
- 他们只有一个参数
- 他们用 infix 关键字标注
局部函数
支持局部函数,局部函数可以访问外部函数的局部变量
fun dfs(graph: Graph) {
fun dfs(current: Vertex, visited: Set<Vertex>) {
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v, visited)
}
dfs(graph.vertices[0], HashSet())
}
高阶函数和lambda表达式
高阶函数是将函数用作参数或返回值的函数
fun <T> lock(lock: Lock, body: () -> T): T {
lock.lock()
try {
return body()
}
finally {
lock.unlock()
}
}
//body拥有函数了理性:()->T。所以它应该是一个不带参数树并且返回T 类型值的函数。
map方法
fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
val result = arrayListOf<R>()
for (item in this)
result.add(transform(item))
return result
}
如果函数字面值只有一个参数, 那么它的声明可以省略(连同 ->),其名称是 it。
//如果生命一个函数类型的可变空量,可以将整个函数型括在括号中并在其后加上问号
var sum: ((Int, Int) -> Int)? = null
Lambda表达式语法
Lambda表达式的完成语法形式
val sum = { x: Int, y: Int -> x + y}
lambda 表达式总是被大括号括着, 完整语法形式的参数声明放在大括号内,并有可选的类型标注, 函数体跟在一个 -> 符号之后。如果推断出的该 lambda 的返回类型不是 Unit,那么该 lambda 主体中的最后一个(或可能是单个)表达式会视为返回值。
带接收者的函数字面值
Kotlin 提供了使用指定的 接收者对象 调用函数字面值的功能。 在函数字面值的函数体中,可以调用该接收者对象上的方法而无需任何额外的限定符。
//这样的函数字面值的类型是一个带有接收者的函数类型
sum : Int.(other: Int) -> Int