2.3定义函数
声明函数
在 kotlin 中用关键字 fun
声明函数:
//定义函数(求两个数里最大值)
fun max(x:Int,y:Int):Int{
//函数体
//通常写法 if控制流
//return if(x>y) x else y
//在Kotlin开发语言中,if是一个表达式,即:它返回一个值。
//由于在此规则下普通if运行的很好,因此没有三元运算符(?:else)
//return (x>y)?x:y //is wrong
//也可以调用Math函数
return Math.max(x,y)
}
由上面例子看出,由fun
声明一个函数,带参函数的参数是由 参数名:数据类型
这样用 :
分隔,函数返回值类型也是用 :
分隔,对于参数后续会再提。
函数的使用
1.通过传统的方法调用函数
val result = max(3,4)
println("3和4最大的是"+ result)
如果在同一个文件内,可直接调用该函数,如果跨文件,则需要引入该函数的相关引用:包名.[类名.]函数名
2.通过 .
调用成员函数
Util().min(3,4) // 创建Util类的实例,调用min方法
声明在类内部的函数需要在外部调用,需要先创建该类实例使用 .
调用其成员函数,编译后我们发现,该类会编译成单独的class文件。
中缀符号
在满足以下条件时,函数也可以通过中缀符号进行调用:
- 它们是成员函数或者是扩展函数
- 只有一个参数
-
使用 infix 关键词进行标记
//给 Int 定义一个扩展方法 infix fun Int.shl(x: Int): Int { ... } 1 shl 2 //用中缀注解调用扩展函数 1.shl(2)
参数
函数参数是用 Pascal 符号定义的 name:type
。参数之间用逗号隔开,每个参数必须指明类型。
//求最小值
fun min(x:Int,y:Int):Int{
return if(x<y) x else y
}
默认参数
函数参数可以设置默认值,当参数被忽略时会使用默认值。这样相比其他语言可以减 少重载。
//求最小值
fun min(x:Int,y:Int=0):Int{
return if(x<y) x else y
}
默认值可以通过在type类型后使用 =
号进行赋值,默认参数可以缺省。
可为空参数(空安全)
函数参数默认是不能为空的,如果需要指定某参可以为空在改参数后追加?
表示可为空:
fun printHello(name: String?): Unit {
if (name != null)
println("Hello ${name}") //标注1
else
println("Hi there!")
}
标注1
用到了字符模板后续会提
不带返回值的参数:Unit
如果函数不会返回任何有用值,那么他的返回类型就是 Unit
. Unit
是一个只有唯一值 Unit
的类型.这个值并不需要被直接返回:
fun printFun(name: String): Unit {
println("Hello ${name}")
// `return Unit` or `return` is optional
}
Unit 返回值也可以省略,比如下面这样:
fun printFun(name: String) {
println("Hello ${name}")
// `return Unit` or `return` is optional
}
单表达式函数
当函数只返回单个表达式时,大括号可以省略并在 = 后面定义函数体
fun double(x: Int): Int = x * 2
在编译器可以推断出返回值类型的时候,返回值的类型可以省略:
fun double(x: Int) = x * 2
明确返回类型
函数必须有明确返回类型,除非他是返回 ` Unit ` 类型的值,Kotlin 并不会对 函数体重的返回类型进行推断,因为函数体中可能有复杂的控制流,他的返回类型未 必对读者可见(甚至对编译器而言也有可能是不可见的)
变长参数
变长参数在Java中也有体现:
public static void printlnLogs(String... logs) {
for (String str : logs) {
System.out.println(str);
}
}
特点就是,只能有一个参数为变长参数,变长参数只能在参数列表末尾。同样Kotlin里的变长参数也符合这样的特征,用 vararg
修饰符进行标记:
fun asList<T>(vararg ts: T): List<T> {
val result = ArrayList<T>()
for (t in ts) //标注2
result.add(t)
return result
}
标注2:for循环语句后续会提
标记后,允许给函数传递可变长度的参数:
val list = asList(1, 2, 3)
只有一个参数可以被标注为 vararg
,刚刚Java的例子改写成Kotlin的:
函数类型(范围)
Kotlin 中可以在文件顶级声明函数-顶级函数,这就意味者你不用像在Java,C#或是Scala一样创建一个类来持有函数。除了顶级函数,Kotlin 函数可以声明为局部的,作为成员函数或扩展函数。
- 顶级函数:声明在文件顶级
- 局部函数:比如在一个函数包含另一函数
- 成员函数:定义在一个类或对象里边的
- 泛型函数:函数的参数数据类型设置为泛型,在Java中也很常见
- 内联函数
- 扩展函数
-
尾递归函数:Kotlin 支持函数式编程的尾递归。这个允许一些算法可以通过循环而不是递归解决问题,从而避免了栈溢出。当函数被标记为 tailrec 时,编译器会优化递归,并用高效迅速的循环代替它。
tailrec fun findFixPoint(x: Double = 1.0): Double = if (x == Math.cos(x)) x else findFixPoint(Math.cos(x))
这段代码计算的是数学上的余弦不动点。Math.cos 从 1.0 开始不断重复,直到值不变为止,结果是 0.7390851332151607 这段代码和下面的是等效的:
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/finall 块中进行使用。当前的尾递归只在 JVM 的后端中可以用
最后附上示例项目Github
[上一篇:2.2定义包] [返回目录] [下一篇:2.4定义变量]