参考原文:http://kotlinlang.org/docs/reference/functions.html
在Kotlin中,使用“fun”关键字声明函数:
fun double(x: Int): Int {
}
val result = double(2)
对于类成员函数,通过类实例加“.”方式使用:
Sample().foo() // create instance of class Sample and calls foo
当函数满足下面几个条件,可以使用中缀方式调用:
Ø 为成员函数或扩展函数
Ø 有且只有一个参数
Ø 使用“infix
”关键字修饰
// Define extension to Int
infix fun Int.shl(x: Int): Int {
...
}
// call extension function using infix notation
1 shl 2
// is the same as
1.shl(2)
fun powerOf(number: Int, exponent: Int) {
...
}
参数可以设置默认值,该参数在使用的时候可以省略;可以减少重载的函数个数。
语法:在类型类型后面使用“ = ”添加默认值:fun read(b: Array, off: Int = 0, len: Int = b.size()) {
...
}
通过继承重写的函数,默认带有父类函数的默认参数;且重写的函数不能在设置默认值。
open class A {
open fun foo(i: Int = 10) { ... }
}
class B : A() {
override fun foo(i: Int) { ... } // no default value allowed
//override fun foo(i: Int = 2) { ... } //error,父类函数已设置默认值,重写函数,不能再设置默认值。
}
调用函数时,可以给传入的参数添加参数名;当一个函数有多个参数时,非常有用。
如,有如下的一个函数:
fun reformat(str: String,
normalizeCase: Boolean = true,
upperCaseFirstLetter: Boolean = true,
divideByCamelHumps: Boolean = false,
wordSeparator: Char = ' ') {
...
}
可以通过该方式调用:
reformat(str)
当该函数的所有参数都没有设置默认值,则需要这样调用:
reformat(str, true, true, false, '_')
此时,可以在调用函数时,给传入的参数添加参数名,增加可读性:
reformat(str,
normalizeCase = true,
upperCaseFirstLetter = true,
divideByCamelHumps = false,
wordSeparator = '_'
)
只需要传入部分参数情况:
reformat(str, wordSeparator = '_')
注:当调用一个Java方法时,不可使用命名参数方式,Java不支持该语法。
Unit
”类型只有一个值,即“
Unit
”。另,可以不显示返回Unit:
fun printHello(name: String?): Unit {
if (name != null)
println("Hello ${name}")
else
println("Hi there!")
// `return Unit` or `return` is optional
}
返回的“Unit”也是可选的,下面的方式等同于返回“Unit”类型:
fun printHello(name: String?) {
...
}
fun double(x: Int): Int = x * 2
编译器可以推断出返回值类型时,函数定义时的返回值类型也可以省略:
fun double(x: Int) = x * 2
函数需要显式定义返回值类型,若没有则表示返回“Unit”。Kotlin不会去推断函数的返回类型当函数的函数体多行时,这种函数有比较复杂的实现,返回类型对于阅读者不是很明显(有时对编译器也不明确),故需要显示定义返回值类型。
vararg
”关键字修饰参数,即可定义为可变数量参数(一般是最后一个参数):
fun asList(vararg ts: T): List {
val result = ArrayList()
for (t in ts) // ts is an Array
result.add(t)
return result
}
该函数可以接收不定个数参数:
val list = asList(1, 2, 3)
在函数内部,被“vararg”修饰的参数实际上是一个数组(Array
一个函数,只能有一个参数可以使用“ vararg”关键字修饰,一般放在最后一个参数。若不是最后一个参数,在使用时,其他的参数可以使用命名参数(Named Arguments)方式;或者函数有一个功能类型参数,可以在函数的后面定义一个Lambda表达式实现。
// vararg参数不是最后一个参数情况
fun asMultipleList(vararg ts: Int, multiple: Int): List {
val resultL = ArrayList()
for(data in ts) {
resultL.add(data * multiple)
}
return resultL
}
//
var multiList = asMultipleList(1, 2, 3, multiple=2)
println(multiList)
//后面更有功能类型参数
fun showInfo(vararg infos: String, show: (info: String) -> Unit) {
for(info in infos) {
show(info)
}
}
//
showInfo("info1", "info2") {
println(it)
}
调用一个“ vararg”函数时,可以一个一个值使用,如“ asList(1, 2, 3)”;也可以直接使用一个存在的数组数据,使用“ *”关键字:
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
在Kotlin中,函数可以定义为顶层(top leve),表示不需要一个类去持有该函数。另外,还可以定义为局部,如类的成员函数,扩展函数。
fun dfs(graph: Graph) {
fun dfs(current: Vertex, visited: Set) {
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v, visited)
}
dfs(graph.vertices[0], HashSet())
}
局部函数,可以访问外层函数的局部变量:
fun dfs(graph: Graph) {
val visited = HashSet()
fun dfs(current: Vertex) {
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v)
}
dfs(graph.vertices[0])
}
class Sample() {
fun foo() { print("Foo") }
}
成员函数,通过“.”方式访问:
Sample().foo() // creates instance of class Sample and calls foo
更多关于成员函数信息,参考类与继承部分。
fun singletonList(item: T): List {
// ...
}
参考内联函数部分。
参考扩展函数部分。
查考高阶函数和Lambda表达式部分。
tailrec
”关键字修饰,编译器可以优化递归,生成一个快速、高效的循环版本。
tailrec fun findFixPoint(x: Double = 1.0): Double
= if (x == Math.cos(x)) x else findFixPoint(Math.cos(x))
等同于下面实现方式:
private fun findFixPoint(): Double {
var x = 1.0
while (true) {
val y = Math.cos(x)
if (x == y) return y
x = y
}
}
使用“tailrec
”修饰的尾递归函数需要满足下面几个条件:
Ø 函数体最后一行执行代码需要是调用函数本身。
Ø 不能在递归的函数后面还有其他的代码。
Ø 递归部分不能放到“ try/catch/finally”中。