定义高阶函数
/
* 高阶函数的定义:如果一个函数接收另一个函数作为参数,或者返回值类型为另一个函数,那么该函数就称为高阶函数
*
* 高阶函数允许让函数类型的参数来决定函数的执行逻辑。即使是同一个高阶函数,只要传入不同的函数参数类型,
* 那么它的执行逻辑和返回结果就可能是完全不同的。
*
* 如果每次调用高阶函数还要定义一个与其函数类型相同参数相匹配的函数,是不是太复杂了?
* 因此kotlin还支持其他多种方式来调用高阶函数,比如Lambda表达式、匿名函数、成员引用。
*/
使用示例,lambda表达式通过匿名类实现的方法可以免去自定义函数的繁琐
fun num1AndNum2(num1:Int,num2:Int,operation:(Int,Int) -> Int): Int {
val result = operation(num1,num2)
return result
}
fun plus(num1: Int,num2: Int):Int{
return num1 + num2
}
fun minus(num1: Int,num2: Int):Int{
return num1 - num2
}
fun main(){
val num1 = 100
val num2 = 80
val result1 = num1AndNum2(num1,num2, ::plus)
val result2 = num1AndNum2(num1,num2, ::minus)
val result3 = num1AndNum2(num1,num2){n1,n2 ->
n1 + n2 /lambda表达式的最后一行代码会自动作为返回值
}
val result4 = num1AndNum2(num1,num2){n1,n2 ->
n1 - n2
}
println("result1 is $result1")
println("result2 is $result2")
}
但是匿名类实现造成了额外的性能开销,使用内联函数,kotlin编译器通过代码替换可以消除因为匿名类实现的性能和内存 开销,关键字为inline
/内联函数:kotlin编译器通过代码替换的方式使得使用lambda表达式不用创建匿名类实例,不造成额外的内存和性能开销。
/一个高阶函数如果接收了两个或者更多函数类型参数,加上inline关键字会自动将所有引用的lambda表达式全部内联
inline fun num1AndNum2(num1:Int,num2:Int,operation:(Int,Int) -> Int): Int {
val result = operation(num1,num2)
return result
}
crossinline解决在高阶函数中国创建了另外的Lambda或者匿名类的实现,并且在这些实现中调用函数类型参数,此时再将高阶函数声明成内联函数,就一定提示错误的问题
内联函数与非内联函数的区别(优劣),部分排除内联noinline关键字
/如果只想内联其中一个Lambda表达式可以使用noinline关键字
/为什么要排除内联?因为非内联的函数类型参数可以自由地传递给其他任何函数,因为它就是一个真实的函数,
/ 而内联的函数参数类型只可以传递给另一个内联函数,这也是最大局限性所在。
inline fun inlineTest(block1 : () -> Unit,noinline block2 : () -> Unit ){}
package com.example.broadcastbestpractice
/另外内联和非内联还有一个重要区别:内联函数所引用的lambda表达式可以使用return关键字进行函数返回,
/ 而非内联只能进行局部返回。
fun printString(str : String, block : (String) -> Unit){
println("printString begin")
block(str)
println("printString end")
}
inline fun runRunnable2(block: () -> Unit){
val runnable = Runnable {
block()
}
runnable.run()
}
/内联函数的lambda表达式中允许使用return关键字,和高阶函数的匿名类实现中不允许使用return关键字之间造成了冲突。
/ 而crossinline关键字就像一个契约,它用于保证内联函数的lambda表达式中一定不会使用return关键字,化解了冲突。
/声明了crossinline后不能使用return,仍然可以用return@runRunnable的写法进行局部返回。
/ 除了在return的使用上有区别,crossinline保留了内联函数其他所有特性。
inline fun runRunnable(crossinline block: () -> Unit){
val runnable = Runnable {
block()
}
runnable.run()
}
fun main(){
println("main start")
val str = ""
printString(str){s ->
println("lambda start")
if (s.isEmpty()) return@printString /lambda表达式不允许直接return,这里表示局部返回,不在执行Lambda剩余代码
println(s)
println("lambda end")
}
println("main end")
}