Kotlin——函数与Lambda表达式
函数是执行特定任务的一段代码。Kotlin对Java的面向对象进行了弥补,增加了函数式编程的支持
函数入门
定义和调用函数
定义函数的语法格式:
fun 函数名(形参列表)[:返回值类型]{
//由零条到多条可执行语句组成的函数
}
Kotlin声明函数必须使用fun关键字
函数名:首字母小写符合命名规范
返回值类型:可以是Kotlin语言所允许的任何数据类型。如果希望声明一个函数没有返回值,则:
省略:省略返回值部分
使用Unit指定返回Unit代表没有返回值 Unit就相当于Java中的void
形参列表:形参列表用于定义该函数可以接受的参数,形参列表由多组“形参名:参数类型”组合而成,之间用","隔开
fun main(args: Array<String>) {
println(max(2, 5))
println(sayHi("abcdefg"))
}
fun max(x: Int, y: Int): Int {
var max = if (x > y) x else y
return max
}
fun sayHi(name:String):String{
println("=====正在执行sayHi函数=====")
return "hello ${name}"
}
函数返回值和Unit
fun main(args: Array<String>) {
foo()
sayHiNull("dddd")
}
fun foo() {
println("foo()函数")
}
fun sayHiNull(name : String): Unit{
println("sayHi函数")
println("welcome${name}")
}
递归函数
在一个函数体内调用自身,称为递归函数,函数递归包含了一种隐式的循环,它会重复执行某段代码而无须循环控制
fun fn(n: Int): Int {
if (n == 0) {
return 1
} else if (n == 4) {
return 4
} else {
return 2 * fn(n - 1) + fn(n - 2)
}
}
单表达式函数
函数只是返回单个表达式,此时可以省略花括号并在=后制定函数体
fun area(x:Int,y:Int):Int = x*y
函数的形参
默认值
语法:
形参名:形参类型=默认值
个数可变的形参
Kotlin允许定义个数可变的参数,从而允许为函数指定数量不确定的形参。在定义函数时,在形参的类型前面添加vararg修饰,则表明该形参可以接受多个参数值。多个参数值被当成数组传入
fun bookStore(a: Int, vararg books: String) {
//books被当成数组处理
for (book in books) {
println(book)
}
println(a)
}
kotlin要求一个函数最多只能带一个个数可变的形参,但是对个数可变的形参位置没有要求
函数重载
与Java类似,Kotlin允许定义多个同名函数,只要形参列表或返回值类型不同就行。如果程序包含了两个或两个以上函数名相同,但形参列表不同的函数,就称为函数重载
fun test() {
println("无参数的test函数")
}
fun test(name: String){
println("有一个String参数的test函数")
}
fun test(age:Int){
println("有一个int参数的test函数")
}
fun test(name:String,age:Int):String{
return "有2个参数带返回值的函数"
}
局部函数
在Kotlin函数体内部定义的函数,放在函数体内定义的函数称为局部函数
局部函数对外部是隐藏的,局部函数只能在封闭函数内有效
//定义函数,该函数的返回值类型为 Int
fun qetMathFunc(type: Strinq , nn: Int) : Int {
//定义一个计算平方的局部函数
fun s伊are (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)}
高阶函数
函数本身也具有自己的类型,函数类型既可以用于变量,也可用作函数的形参,还可以作为函数的返回值类型
使用函数类型
Kotlin的每个函数都有特定的类型,函数类型由函数的形参列表、->和返回值类型组成
fun foo(a:Int,name:String) -> String{}
该函数的函数类型就是 (Int,String)->String
fun bar(width:Double,height:Double){}
该函数的类型:(Double,Double)->Unit或(Double,Double)
fun test(){}
该函数的类型 () 或 ()->Unit
//定义一个变量,其类型为(Int,Int)->Int
var myfun : (Int,Int)->Int
可将函数赋值给变量
fun main(args: Array<String>) {
var myfun = ::pow
println(myfun(3, 5))
myfun = ::areaa
println(myfun(3, 4))
}
fun areaa(a:Int,b:Int):Int{
return a * b
}
/**
* 定义一个计算乘方的函数
*/
fun pow(base:Int,exponent:Int):Int{
var result =1
for (i in 1..exponent){
result *= base
}
return result
}
- 当直接访问一个函数的函数引用,而不是调用函数时,需要在函数名前添加两个冒号,而且不能再函数后面添加圆括号,一旦添加括号,就变成了调用函数,而不是访问函数引用。
使用函数类型作为形参类型
如果希望调用函数时能动态传入代码,就需要在函数中定义函数类型的形参,这样可以在调用该函数时传入不同的函数作为参数。从而动态改变这些代码
fun main(args: Array<String>) {
var data = arrayOf(3, 4, 5, 6, 7, 8)
println(map(data, ::square))
println(map(data, ::add))
}
fun map(data: Array<Int>, fn: (Int) -> Int): List<Int> {
//创建一个新的数组
// Array<Int>(data.size,{0})
val mutableList = mutableListOf<Int>()
for (index in data.indices) {
mutableList.add(index, fn(data[index]))
}
return mutableList
}
fun square(n: Int): Int {
return n * n
}
fun add(n: Int): Int {
return n + 1
}
使用函数类型作为返回值类型
fun main(args: Array<String>) {
var mathFunc = getMathFunc("square")
println(mathFunc(3))
var cubeFun = getMathFunc("cube")
println(cubeFun(3))
}
/**
* 获取数学函数
*/
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 (i in 2..n) {
result *=i
}
return result
}
return when (type) {
"square" -> ::square
"cube" -> ::cube
else -> ::factorial
}
}
局部函数与Lambda表达式
使用Lambda表达式代替局部函数
上面的函数我们可以使用Lambda表达式来进行改造
when (type) {
"square" -> return {n:Int->n*n}
"cube" -> return {n:Int -> n*n*n}
else -> return {n:Int ->
var result = 1
for (i in 2..n) {
result *=i
}
result
}
}
Lambda的特点:
- Lambda表达式总是被大括号括着
- 定义Lambda表达式不需要fun关键字,无须指定函数名
- 形参列表在->之前声明,参数类型可以省略
- 函数体需要放在->之后
- 函数的最后一个表达式自动被作为Lambda表达式的返回值,无须使用return关键字
Lambda表达式
Lambda表达式的语法:
{
(形参列表)->
//零条到多条可执行语句
}
利用上下文推断类型
完整的Lambda表达式需要定义形参类型,如果Kotlin可以根据Lambda表达式上下文推断出形参类型,那么Lambda表达式可以省略形参类型
var square:(Int)->Int = {n -> n*n}
省略形参名
Lambda表达式如果只有一个形参,那么Kotlin允许省略Lambda表达式的形参名,如果省略了形参名,那么此时 ->也不需要了,可以使用it来代表形参
var square:(Int) -> Int = {it*it}
调用Lambda表达式的约定
Kotlin语言约定,如果函数的最后一个参数是函数类型,且打算传入一个Lambda表达式作为相应的参数,那么就允许在圆括号之外指定Lambda表达式
var rt = list.dropWhile(){it.leng>3}
匿名函数
用法
var test = fun(x:Int,y:Int):Int{
return x+y
}
- 如果可以推断出匿名函数的形参类型,那么匿名函数允许省略形参类型
- 如果使用普通代码块作为函数体,则匿名函数需要显式指定返回值类型,如果使用单表达式作为函数体,则无须指定返回值类型,由系统自动推断