Kotlin - 函数
Kotlin 是一种静态类型语言,因此,function 在其中扮演着重要角色。我们在前几章的示例中已经很熟悉 function 了。function 是一段用于执行特定任务的代码块。所有现代编程语言都支持 function,它们也被称为 methods 或 subroutines。
从广义上讲,function 会接收一些输入(称为 parameters),对这些输入执行某些操作,并最终返回一个值。
Kotlin 内置 Functions
Kotlin 提供了许多内置 function,我们在示例中已经使用过许多内置 function。例如 print() 和 println() 是最常用的内置 function,用于将输出打印到屏幕上。
示例
fun main(args: Array<String>) {
println("Hello, World!")
}
用户定义 Functions
Kotlin 允许我们使用关键字 fun 创建自己的 function。用户定义的 function 可以接收一个或多个 parameters,执行操作并将该操作的结果作为值返回。
语法
fun functionName(){
// function 体
}
定义好 function 后,我们可以在需要时多次调用它。以下是调用 Kotlin function 的简单语法:
functionName()
示例
以下示例定义并调用了一个用户定义的 function,它将打印简单的 "Hello, World!":
fun main(args: Array<String>) {
printHello()
}
fun printHello(){
println("Hello, World!")
}
运行上述 Kotlin 程序时,将生成以下输出:
Hello, World!
Function Parameters
用户定义的 function 可以接收零个或多个 parameters。parameters 是可选的,可以根据需要使用。例如,我们上面定义的 function 就没有使用任何 parameter。
示例
以下示例编写了一个用户定义的 function,它将两个给定的数字相加并打印它们的和:
fun main(args: Array<String>) {
val a = 10
val b = 20
printSum(a, b)
}
fun printSum(a:Int, b:Int){
println(a + b)
}
运行上述 Kotlin 程序时,将生成以下输出:
30
返回值
Kotlin function 根据需要返回一个值。返回值是完全可选的。
要返回一个值,请使用 return 关键字,并在 function 的括号后指定返回类型。
示例
以下示例编写了一个用户定义的 function,它将两个给定的数字相加并返回它们的和:
fun main(args: Array<String>) {
val a = 10
val b = 20
val result = sumTwo(a, b)
println( result )
}
fun sumTwo(a:Int, b:Int):Int{
val x = a + b
return x
}
运行上述 Kotlin 程序时,将生成以下输出:
30
返回 Unit 的 Functions
如果 function 不返回有用的值,其返回类型就是 Unit。Unit 是一种只有一个值(即 Unit)的类型。
fun sumTwo(a:Int, b:Int):Unit{
val x = a + b
println( x )
}
Unit 返回类型声明也是可选的。上述代码等价于:
fun sumTwo(a:Int, b:Int){
val x = a + b
println( x )
}
Kotlin 递归函数
递归函数在许多场景中很有用,比如计算一个数的阶乘或生成斐波那契数列。Kotlin 支持递归,这意味着 Kotlin 函数可以调用自身。
语法
fun functionName(){
...
functionName()
...
}
示例
以下是一个 Kotlin 程序,用于计算数字 10 的阶乘:
fun main(args: Array<String>) {
val a = 4
val result = factorial(a)
println( result )
}
fun factorial(a:Int):Int{
val result:Int
if( a <= 1){
result = a
}else{
result = a*factorial(a-1)
}
return result
}
运行上述 Kotlin 程序时,将生成以下输出:
24
Kotlin 尾递归
如果一个递归函数对自身的调用是其执行的最后操作,则该递归函数符合 尾递归 的条件。
示例
以下是一个使用尾递归计算数字 10 阶乘的 Kotlin 程序。在此,我们需要确保乘法运算在递归调用之前执行,而不是之后。
fun main(args: Array<String>) {
val a = 4
val result = factorial(a)
println( result )
}
fun factorial(a: Int, accum: Int = 1): Int {
val result = a * accum
return if (a <= 1) {
result
} else {
factorial(a - 1, result)
}
}
运行上述 Kotlin 程序时,将生成以下输出:
24
Kotlin 尾递归在计算阶乘或对大数进行其他处理时非常有用。因此,为了避免 java.lang.StackOverflowError,必须使用尾递归。
高阶函数
高阶函数是一个将另一个函数作为参数和/或返回一个函数的函数。
示例
以下是一个函数,它接受两个整数参数 a 和 b,此外还接受另一个函数 operation 作为参数:
fun main(args: Array<String>) {
val result = calculate(4, 5, ::sum)
println( result )
}
fun sum(a: Int, b: Int) = a + b
fun calculate(a: Int, b: Int, operation:(Int, Int) -> Int): Int {
return operation(a, b)
}
运行上述 Kotlin 程序时,将生成以下输出:
9
在这里,我们调用了 高阶函数,传入两个整数值和函数参数 ::sum。:: 是 Kotlin 中通过名称引用函数的记法。
示例
让我们再看一个示例,其中一个函数返回另一个函数。这里我们定义了一个高阶函数,它返回一个函数。(Int) -> Int 表示 square 函数的参数和返回类型。
fun main(args: Array<String>) {
val func = operation()
println( func(4) )
}
fun square(x: Int) = x * x
fun operation(): (Int) -> Int {
return ::square
}
运行上述 Kotlin 程序时,将生成以下输出:
9
Kotlin Lambda 函数
Kotlin lambda 是一个没有名称的函数,使用花括号 {} 定义,可以接受零个或多个参数以及函数体。
函数体写在变量(如果有的话)之后,后跟 -> 操作符。
语法
{variable with type -> body of the function}
示例
fun main(args: Array<String>) {
val upperCase = { str: String -> str.toUpperCase() }
println( upperCase("hello, world!") )
}
运行上述 Kotlin 程序时,将生成以下输出:
HELLO, WORLD!
Kotlin 内联函数
inline 函数使用 inline 关键字声明。使用内联函数可以提升高阶函数的性能。内联函数告诉编译器将参数和函数复制到调用点。
示例
fun main(args: Array<String>) {
myFunction({println("Inline function parameter")})
}
inline fun myFunction(function:()-> Unit){
println("I am inline function - A")
function()
println("I am inline function - B")
}
运行上述 Kotlin 程序时,将生成以下输出:
I am inline function - A Inline function parameter I am inline function - B
测试时间 (面试与考试准备)
Q 1 - 以下关于 Kotlin 函数的描述哪个是正确的?
A - Kotlin 函数可以接受一个或多个参数
B - Kotlin 函数可以是递归的
C - Kotlin 函数可以返回值。
D - 以上全部
答案:D
解释
所有给出的陈述关于 Kotlin 函数都是正确的
Q 2 - 以下程序的输出是什么:
fun main(args: Array<String>) {
val a = 100000
val result = factorial(a)
println( result )
}
fun factorial(a:Int):Int{
val result:Int
if( a <= 1){
result = a
}else{
result = a*factorial(a-1)
}
return result
}
A - 将打印 0
B - 将仅产生警告
C - 编译将因错误停止
D - 以上皆非
答案:C
解释
这将因 java.lang.StackOverflowError 而停止,因为编译器无法调用大量递归函数调用。
Q 2 - 什么是尾递归?
A - 先执行计算,然后执行递归调用。
B - 尾递归避免了栈溢出的风险
C - 递归调用将当前步骤的结果传递给下一个递归调用
D - 以上全部
答案:D
解释
A、B 和 C 所有陈述关于尾递归都是正确的。