定义
在面向函数的编程语言中,函数是十分重要的,kotlin通过fun关键字定义函数:
fun double(x: Int): Int {
}
调用
(1)通过传统方法调用:
val result = double(3)
(2)对于成员函数用点:
gobj.attack() // 创建gobj对象,调用attack函数
(3)中缀符号:
当函数满足如下条件,允许使用中缀符号调用:
--成员函数或拓展函数;
--只有一个参数;
--使用infix关键字标记。
// 定义Int的拓展
infix fun Int.shl(x: Int): Int {
...
}
// 用中缀符号调用拓展函数
1 shl 2
// 等同于
1.shl(2)
参数
函数的参数使用pascal符号(参数名字:类型),参数之间用逗号区分,每个参数必须指定类型。fun powerOf(number: Int, exponent: Int) {
...
}
默认参数
函数的参数可以有默认值,当参数被忽略的时候,使用默认值。相对其它语言而言,减少了重载。
fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size()) {
...
}
默认值的定义在类型的后面使用=。
重写函数总是使用父函数的默认值,当重写一个有默认值的函数时,默认值必须从签名中被删除。
open class A {
open fun foo(i: Int = 10) { ... }
}
class B : A() {
override fun foo(i: Int) { ... } // 不允许默认值
}
命名参数
调用函数的时候,函数的参数可以被命名,在函数的参数非常多,或者都有默认值时,会十分的方便。
看例子:
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函数。
无返回值函数
函数没有返回值,那么返回类型就是unit,无需指定。单表达式函数
当函数只返回单个表达式时,大括号可以省略并在 = 后面定义函数体。
fun double(x: Int): Int = x*2
在编译器可以推断出返回值类型的时候,返回值的类型可以省略。
fun double(x: Int) = x * 2
指定返回类型
除了返回unit,函数包含block body的时候必须指定返回类型。
变长参数(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)
只有一个参数可以被标注为 vararg 。加入vararg并不是列表中的最后一个参数,那么后面的参数需要通过命名参数语法进行传值,再或者如果这个参数是函数类型,就需要通过lambda法则。
当调用变长参数的函数时,我们可以一个一个的传递参数,比如 asList(1, 2, 3),或者我们要传递一个 array 的内容给函数,我们就可以使用 * 前缀操作符:
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)