注:编码工具为IntelliJ
目录
Kotlin的lambda表达式实现原理
高阶函数
函数作为函数参数
函数作为函数的返回值
高阶函数使用案例
回调
高阶函数配合扩展函数使用
函数作为最后一个参数的调用方式
模仿监听
Kotlin的lambda表达式实现原理
Kotlin内部定义了一系列FunctionX接口,在Function.kt文件中,开发者定义的lambda表达式(匿名函数),Kotlin底层会通过实现FunctionX接口的方式实现。
package step_eight
fun main() {
var method = { println("lambda表达式/匿名函数")}
var method2 = {string: String -> println(string)}
var method3 : (Int, Int) -> String = {a, b -> (a + b).toString()}
}
反编译为Java代码后:
public final class LambdaTruthKt {
public static final void main() {
Function0 method = (Function0)null.INSTANCE;
Function1 method2 = (Function1)null.INSTANCE;
Function2 method3 = (Function2)null.INSTANCE;
}
// $FF: synthetic method
public static void main(String[] var0) {
main();
}
}
上面的Function0、Function1、Function2都是定义在Function.kt文件中的接口,Function.kt的部分内容:
// Auto-generated file. DO NOT EDIT! package kotlin.jvm.functions public interface Function0: Function { public operator fun invoke(): R } public interface Function1 : Function { public operator fun invoke(p1: P1): R } public interface Function2 : Function { public operator fun invoke(p1: P1, p2: P2): R } public interface Function3 : Function { public operator fun invoke(p1: P1, p2: P2, p3: P3): R }
高阶函数
函数作为函数参数
可以将lambda表达式(匿名函数)或者满足作为参数的函数的声明类型的普通函数的函数引用作为实际参数传给函数。
lambda表达式(匿名函数)作为函数的最后一个参数传递时,可以放在()的外面。
package step_eight
private fun show(str: String, action: (String) -> Unit) = action(str)
private fun calc(num1: Int, num2: Int, action: (Int, Int) -> Int) = action(num1, num2)
fun main() {
// lambda表达式(匿名函数)作为实际参数
show("Higher Order Function", action = { println(it)})
// 普通函数的函数引用作为实际参数
show("Higher Order Function", ::println)
val num1 = 30
val num2 = 90
println("$num1 + $num2 = ${calc(num1, num2, { i, j -> i + j })}")
println("$num1 - $num2 = ${calc(num1, num2, { i, j -> i - j })}")
println("$num1 * $num2 = ${calc(num1, num2, { i, j -> i * j })}")
println("$num1 / $num2 = ${calc(num1, num2, { i, j -> i / j })}")
}
输出:
Higher Order Function Higher Order Function 30 + 90 = 120 30 - 90 = -60 30 * 90 = 2700 30 / 90 = 0
函数作为函数的返回值
函数执行的结果是一个函数,还能执行一次。暂时想不到有什么用途。
package step_eight
private fun op() = { msg: String -> println(msg) }
fun main() {
// op的执行结果是一个函数,还能执行一次,所以有两组()
op()("Higher Order Function")
// 复杂情况
var method = fun(a: Int, b: Int): (Int, Int) -> String =
{ i, j -> "$i + $j = ${i + j} n a = $a n b = $b" }
println(method(10, 18)(100, 200))
var method2 : (String) -> (String) -> (Boolean) -> (Int) ->(String) -> Int =
{
println("第一层 it = $it");
{
println("第二层 it = $it");
{
println("第三层 it = $it");
{
println("第四层 it = $it");
{
println("第五层 it = $it");
it.length
}
}
}
}
}
println(method2("Higher")("Order")(true)(10000)("Function"))
}
输出:
Higher Order Function 100 + 200 = 300 a = 10 b = 18 第一层 it = Higher 第二层 it = Order 第三层 it = true 第四层 it = 10000 第五层 it = Function 8
高阶函数使用案例
回调
package step_eight
private fun login(name: String, pwd: String, response: (String, String) -> Unit){
if("root" == name && "123456" == pwd){
response("登录成功", "200")
}else{
response("用户名或密码错误", "400")
}
}
fun main() {
login("admin", "admin"){
msg, code ->
println("msg = $msg, code = $code")
}
}
package step_eight
private fun login(name: String, pwd: String, response: (String, String) -> Unit){
if("root" == name && "123456" == pwd){
response("登录成功", "200")
}else{
response("用户名或密码错误", "400")
}
}
fun main() {
login("admin", "admin"){
msg, code ->
println("msg = $msg, code = $code")
}
}
输出:
msg = 用户名或密码错误, code = 400
高阶函数配合扩展函数使用
package step_eight
private fun T.work(action: T.()-> R): R = action()
fun main() {
println("kouniqiwa".work {
println(this)
"hi"
})
println(123.work { this.times(10) })
println("I LOVE YOU BABY".work { lowercase() })
}
输出:
kouniqiwa hi 1230 i love you baby
函数作为最后一个参数的调用方式
package step_eight
private fun show(msg: String, func: (String) -> Unit) = func(msg)
fun main() {
show("time machine", func = { println(it) })
show("Stone", { println(it) })
show("Happy") { println(it) }
}
输出:
time machine Stone Happy
模仿监听
package step_eight
class ListenerOp{
val actions = arrayListOf<(T) -> Unit>()
val values = arrayListOf()
fun action(){
if(actions.isEmpty()){
println("没有监听器")
}else{
actions.forEachIndexed { index, function ->
function(values[index])
}
}
}
fun setListener(value: T, action: (T) -> Unit){
values += value
actions += action
}
}
fun main() {
val listener = ListenerOp()
listener.action()
listener.setListener("Hi"){ println(it) }
listener.setListener("What Do I Call You"){ println(it) }
listener.setListener("Destiny"){ println(it) }
fun funcRef(t: T){
println(t)
}
listener.setListener("century ago", ::funcRef)
fun console(str: String) = println(str)
listener.setListener("测试", ::console)
val r = ::console
listener.setListener("测试函数引用", r)
listener.action()
}
输出:
没有监听器 Hi What Do I Call You Destiny century ago 测试 测试函数引用



