Kotlin函数总结(一)

336 阅读5分钟

1.Kotlin 尾递归函数

当函数调用自身作为执行的最后一行代码时,使用尾递归。不能在try、catch、finally中使用。要使用tailrec关键字修饰。
编译器会对尾递归进行修改,进行优化,形参基于循环的版本,减少内存消耗。
// 定义计算阶乘的函数
fun fact(n: Int): Int{
if (n == 1){
return 1
} else {
return n * fact(n - 1)
}
}

// 使用尾递归函数的语法
tailrec fun factRec(n: Int, total: Int = 1): Int =
if (n == 1) total else factRec(n - 1, total * n)
fun main(args: Array<String>) {
println(factRec(5))
}

2.可变个数形参

使用vararg关键字修饰,表示可以接受多个参数值。多个参数值以数组形式传入。

// 定义了形参个数可变的函数
fun test(vararg books : String , num: Int) {
// books被当成数组处理
for (i in books.indices) {
println(books[i])
}
println(num)
}
fun main(args: Array<String>) {
// 调用test()函数
test("111", "222", num = 20)
var arr = arrayOf("111", "222")
// 将数组的多个元素传给个数可变的参数
test(*arr, num = 20)
}

kotlin要求一个函数最多只能带一个可变个数形参。

3.函数重载


kotlin函数重载与java类似。也只能通过形参列表进行区分。形参个数不同、形参类型不同都算函数重载。但形参名字不同、返回值类型不同、修饰符不同都不算函数重载。

// 下面定义了3个test()函数,但函数的形参列表不同
// 系统可以区分它们,这被称为函数重载
fun test() {
println("无参数的test()函数")
}
// 该函数类型为(String): Unit
fun test(msg:String) {
println("重载的test()函数${msg}")
}
// 该函数类型为(Int): String
fun test(msg: Int): String {
println("重载的test()函数${msg},带返回值")
return "test"
}
fun main(args: Array<String>){
// 调用test()时没有传入参数,因此系统调用上面没有参数的test()函数
test()
// 调用带String参数的test()函数
test("fkjava")
// 调用带Int参数的test()函数,该函数返回字符串
var rt = test(30)
println(rt)
}


4.局部函数


在函数体内定义函数叫做局部函数。默认情况下,局部函数对外隐藏,只能做其封闭(enclosing)函数内有效,其封闭函数也可以返回局部函数。

// 定义函数,该函数的返回值类型为Int
fun getMathFunc(type: String , nn: Int) : Int {
// 定义一个计算平方的局部函数
fun square(n: Int) : Int { // ①
return n * n
}
// 定义一个计算立方的局部函数
fun cube(n: Int) : Int { // ②
return n * n * n
}
// 定义一个计算阶乘的局部函数
fun factorial(n: Int) : Int { // ③
var result = 1
for (index in 2 .. n) {
result *= index
}
return result
}
when(type) {
// 调用局部函数
"square" -> return square(nn)
"cube" -> return cube(nn)
else -> return factorial(nn)
}
}
fun main(args: Array<String>) {
println(getMathFunc("square", 3)) // 输出9
println(getMathFunc("cube", 3)) // 输出27
println(getMathFunc("", 3)) // 输出6
}

上面代码封闭函数没有局部函数返回,所以作用于只能在封闭函数内部。
但是,如果封闭函数将局部函数返回,且使用变量保存了封闭函数的返回值,就会放大局部函数的作用域。

5.高阶函数


5.1使用函数类型


fun main(args: Array<String>) {
// 定义一个变量,其类型为(Int , Int) -> Int
var myfun : (Int , Int) -> Int
// 定义一个变量,其类型为(String) -> Unit
var test : (String)
// 定义一个计算乘方的函数
fun pow(base: Int , exponent:Int) : Int {
var result = 1
for( i in 1 .. exponent) {
result *= base
}
return result
}
// 将::pow函数赋值给myfun,则myfun可当成pow使用
myfun = ::pow
println(myfun(3 , 4)) // 输出81
// 定义一个计算面积的函数
fun area(width: Int, height:Int) : Int {
return width * height
}
// 将area函数赋值给myfun,则myfun可当成area使用
myfun = ::area
println(myfun(3, 4)) // 输出12
}

通过使用函数变量的类型,可以让myfun()在不同时间指向不同函数,增加程序灵活性。

5.2使用函数类型作为形参类型


// 定义函数类型的形参,其中fn是(Int) -> Int类型的形参
fun map(data : Array<Int>, fn: (Int) -> Int) : Array<Int> {
var result = Array<Int>(data.size, {0})
// 遍历data数组中每个元素,并用fn函数对data[i]进行计算
// 然后将计算结果作为新数组的元素
for (i in data.indices) {
result[i] = fn(data[i])
}
return result
}
// 定义一个计算平方的函数
fun square(n: Int) : Int {
return n * n
}
// 定义一个计算立方的函数
fun cube(n: Int) : Int {
return n * n * n
}
// 定义一个计算阶乘的函数
fun factorial(n: Int) : Int {
var result = 1
for (index in 2 .. n) {
result *= index
}
return result
}
fun main(args: Array<String>) {
var data = arrayOf(3 , 4 , 9 , 5, 8)
println("原数据${data.contentToString()}")
// 下面程序代码3次调用map()函数,每次调用时传入不同的函数
println("计算数组元素的平方")
println(map(data , ::square).contentToString())
println("计算数组元素的立方")
println(map(data , ::cube).contentToString())
println("计算数组元素的阶乘")
println(map(data , ::factorial).contentToString())
}

定义函数类型的形参之后,就可以动态地调用传入函数,可以动态地改变调用函数的代码。这是一种命令模式。

5.3使用函数类型作为返回值类型


// 定义函数,该函数的返回值类型为(Int) -> Int
fun getMathFunc(type: String): (Int) -> Int {
// 定义一个计算平方的局部函数
fun square(n: Int) : Int { // ①
return n * n
}
// 定义一个计算立方的局部函数
fun cube(n: Int) : Int { // ②
return n * n * n
}
// 定义一个计算阶乘的局部函数
fun factorial(n: Int) : Int { // ③
var result = 1
for (index in 2 .. n) {
result *= index
}
return result
}
when(type) {
// 返回局部函数
"square" -> return ::square
"cube" -> return ::cube
else -> return ::factorial
}
}
fun main(args: Array<String>) {
// 调用getMathFunc(),程序返回一个(Int)->Int类型的函数
var mathFunc = getMathFunc("cube") // 得到cube函数
println(mathFunc(5)) // 输出125
mathFunc = getMathFunc("square") // 得到square函数
println(mathFunc(5)) // 输出25
mathFunc = getMathFunc("other") // 得到factorial函数
println(mathFunc(5)) // 输出120
}

getMathFunc()函数,其返回值类型为(Int)->Int,是一种函数类型。