kotlin学习二:函数
函数书写:
声明:fun
fun double(x: Int): Int {
return 2 * x
}
入口函数:main
fun main() {
println("Hello world!")
}
参数 name: type
函数参数使用 Pascal 表示法定义,即 name: type。参数用逗号隔开。每个参数必须有显式类型:
fun powerOf(number: Int, exponent: Int) { /*……*/ }
默认参数 name: type=
fun read(b: Array, off: Int = 0, len: Int = b.size) { /*……*/ }
默认值通过类型后面的 = 及给出的值来定义。
覆盖方法,总是默认覆盖原来默认参数,不能书写默认参数。
函数调用
//调用函数默认参数情况,
fun foo(bar: Int = 0, baz: Int) { /*……*/ }
//位置参数调用:默认参数在前的情况1
foo(baz = 1) // 使用默认值 bar = 0
fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { /*……*/ }
//默认参数在前的情况2
foo(1) { println("hello") } // 使用默认值 baz = 1
foo(qux = { println("hello") }) // 使用两个默认值 bar = 0 与 baz = 1
//多参数,具名参数情况
fun reformat(str: String,
normalizeCase: Boolean = true,
upperCaseFirstLetter: Boolean = true,
divideByCamelHumps: Boolean = false,
wordSeparator: Char = ' ') {
/*……*/
}
//默认调用
reformat(str, true, true, false, '_')
//增加可读性可采用具名参数 调用
reformat(str,
normalizeCase = true,
upperCaseFirstLetter = true,
divideByCamelHumps = false,
wordSeparator = '_'
)
//如果我们不需要所有的参数:可以巧妙的直接传入需要更改的参数
reformat(str, wordSeparator = '_')
//特殊情况,传入需要更改的情况时候,所有位置参数放在具名参数之前
f(1, y = 2) √
f(x = 1, 2) ×
无意义返回值:Unit
返回无意义类型 void,或者无返回值:
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}
函数多种写法
基本:变量类型写变量的后面,
fun sum(a: Int, b: Int): Int {
return a + b
}
利用类型推断,省略返回值类型书写:
fun sum(a: Int, b: Int) = a + b
中缀函数 infix
中缀函数,一种表示方法,忽略该调用的点与圆括号
例如:
infix fun Int.shl(x: Int): Int { …… }
// 用中缀表示法调用该函数
1 shl 2
// 等同于这样
1.shl(2)
infix调用的优先级:
- 低于算术操作符、类型转换以及
rangeTo
操作符 - 高于布尔操作符
&&
与||
、is-
与 `in-检测以及其他的操作符
使用范围
- 它们必须是成员函数或扩展函数;
- 它们必须只有一个参数;
- 其参数不得接受可变数量的参数且不能有默认值。
函数作用域
支持成员函数,局部函数
局部函数,可以访问闭包,上一层函数的局部变量;
成员函数:可以直接通过实例、类.方法调用
Sample().foo() // 创建类 Sample 实例并调用 foo
尾部递归函数:tailrec
当一个函数用 tailrec
修饰符标记并满足所需的形式时,编译器会优化该递归,留下一个快速而高效的基于循环的版本:
使用条件:
要符合 tailrec
修饰符的条件的话,函数必须将其自身调用作为它执行的最后一个操作。在递归调用后有更多代码时,不能使用尾递归,并且不能用在 try/catch/finally 块中。
优点:允许一些通常用循环写的算法改用递归函数来写,而无堆栈溢出的风险。
eg:
val eps = 1E-10 // "good enough", could be 10^-15
tailrec fun findFixPoint(x: Double = 1.0): Double
= if (Math.abs(x - Math.cos(x)) < eps) x else findFixPoint(Math.cos(x))
相当于:
val eps = 1E-10 // "good enough", could be 10^-15
private fun findFixPoint(): Double {
var x = 1.0
while (true) {
val y = Math.cos(x)
if (Math.abs(x - y) < eps) return x
x = Math.cos(x)
}
}
参考链接:
https://www.kotlincn.net/docs/reference/lambdas.html