kotlinKotlin 知识

Kotlin 小细节记录(7)函数-高阶函数-Lambda

2022-03-03  本文已影响0人  zcwfeng

函数-高阶函数-Lambda

1. 函数调用省略

var method01:(Int)->Unit = {value -> println(value)}
fun main() {
    method01(111)
    method01.invoke(22222)
}

函数调用省略invoke() 直接使用 (......)

2. 函数声明与实现

: (参数)->返回
= {参数->方式}

的步理解声明和实现, 有点C++的身影

    var method02 : (Int)->String // 先声明
    method02 = fun(value : Int) : String= value.toString() // 后实现
    println(method02(99))

    // 用 先声明 的类型,来 自动推断
    var method03 : (Int)->String // 先声明
    method03 = fun(value)  = value.toString() // 后实现
    println(method03(99))

    // 声明 + 实现 一气呵成
    var method04 : (Int) -> String/*左边是声明*/= {value-> "$value aaa"}/*右边是实现*/
    println(method04(77))

3. 函数的几种类型接收和返回参数

fun showAction(action: (Int) -> String) {
    println(action(88))
}

fun lambdaImpl(value: Int) = "my value is$value"


   showAction(::lambdaImpl)
    val r1: Function1<Int,String> = ::lambdaImpl
    val r2: (Int) -> String = ::lambdaImpl
    val r3: Int.() -> String = r2

多个lambda的函数

fun lambdaMulti(lambda1:(String)->Unit,lambda2:(Int)->Unit){
......
}
--------------------------------
    lambdaMulti({},{})
    lambdaMulti({
        
    }){
        
    }

一个Lambda嵌套的有趣例子

val fan: (String) -> (String) -> (Boolean) -> (Int) -> (String) -> Int = {
        {
            {
                {
                    {
                        99
                    }
                }
            }
        }
    }
    println(fan("AAA")("bbb")(false)(44)("aaaa"))

模拟添加事件,lambda 没法用泛型,用any替代


class AndroidClickListener<T> {
    private val actions = arrayListOf<(T?) -> Unit>()
    private val valuse = arrayListOf<T?>()

    fun addListener(value: T?, action: (T?) -> Unit) {
        if (!actions.contains(action)) {
            actions += action
            valuse += value
        }
    }

    fun touchListeners() {
        if (actions.isEmpty()) {
            println("not action")
            return
        }
        actions?.forEachIndexed { index, item ->
            item.invoke(valuse[index])
        }
    }
}

fun <T> show(value: T?) {
    println("event is value:$value")
}

fun main() {
    val func = AndroidClickListener<String>()
    func.touchListeners()
    func.addListener("zcwfeng") {
        println("事件执行 ,value is $it")
    }
    //lambda 没法用泛型,用any替代
    var result: (Any?) -> Unit = ::show
    val method1: (Any) -> Unit = {}
    func.touchListeners()

    println()

    // 我想传递 事件
    func.addListener("zcwfeng", ::show)
    // lambda无法玩泛型
    func.touchListeners()
}

4. 函数定义

fun study01() = {
}

这句话是两个函数

看个复杂点的例子,包含一个lambda函数

fun study01() = { name:String,age:Int->
    true
    name
    age
    "name is:$name,age is: $age"
}

fun study02() = {lambdaAction:(Int,Int)->String,studyInfo:String->
    false
    '男'
    val lambdaAction = lambdaAction(10,10)
    println("lambdaAction function result is :$lambdaAction + $studyInfo")
}


fun main() {
    println(study01()("zcwfeng",99))
    study02()({n1,n2->
        "两个num相加得到的结果:${n1 + n2}"
    },"zcwfeng")
}

------------------------
来看函数的返回类型

fun study03() = { str:String,num:Int,lambda1:(String)->Unit,lambda2:(Int)->Unit ->
    lambda1(str)
    lambda2(num)
}

返回类型 (String,Int,(String)->Unit,(Int)->Unit) -> Unit

study03()("zcwfeng",11,{
        println("lambda1 value is:$it")
    }){
        println("lambda2 value is:$it")
    }

最后一个lambda可以写到()后面也可以卸载参数里study03()("","",{},{})或者study03()("","",{}){}

泛型化
fun <T1, T2, R1, R2> study04() = { str: T1, num: T2, lambda1: (T1) -> R1, lambda2: (T2) -> R2 ->
    println("lambda1 is value ${lambda1(str)}")
    println("lambda2 is value ${lambda2(num)}")

}

  study04<String, Int, Int, String>()("zcwfeng", 100, {
        "$it".length// 类似rx str to int
    }, {
        "$it to String"// int to string
    })

5. 模仿RXJava 的操作符

fun main() {
    create {
        "zcwfeng"
    }.map {
        it.length
    }.map {
        "长度是$it"
    }.map {
        "[$it]"
    }.compose {
        println(it)
    }
}

//保存map
class Helper<T>(private var item: T) {
    // 链式调用
    fun <R> map(lambda: (T) -> R) = Helper(item)
    fun compose(action: (T) -> Unit) = action(item)
}
fun <R> create(action: () -> R) =  Helper(action())

通过扩展函数简化后的代码


fun main() {
    create {
        "zcwfeng"
    }.map {
        length
    }.map {
        "长度是$this"
    }.map {
        "[$this]"
    }.compose {
        println(this)
    }
}

//保存map
class Helper<T>(var item: T)
// 链式调用
fun <T,R> Helper<T>.map(lambda: T.() -> R) = Helper(lambda(item))
fun<T> Helper<T>.compose(action: T.() -> Unit) = action(item)
fun <R> create(action: () -> R) = Helper(action())

6. forEach 内置函数仿写

使用

    listOf("aaa", "bbb", "ccc")
        .forEach {
            println(it)
        }
    println();
    listOf("aaa", "bbb", "ccc")
        .mForeach {
            println(it)
        }
----------
inline fun <T> Iterable<T>.mForeach(lambda: (T) -> Unit) = kotlin.run {for (item in this) lambda(item) }

如果Lambda中println(this)我不想用it,那么稍微改造下

inline fun <T> Iterable<T>.mForeach(lambda: T.() -> Unit) = kotlin.run {for (item in this) lambda(item) }

不用系统的run,自己实现
inline fun <T> Iterable<T>.mForeach(lambda: T.() -> Unit) = r { for (item in this) lambda(item) }
inline fun <R> r(lambda: () -> R) = lambda()

小技巧:T.() 扩展写法持有this----(T) 持有的是it

7. 仿写let内置函数

 "zcwfeng".let {
        'a'
        0
        99.99
    }
    "zcwfeng".mLet {
        '2'
        111
        println("value is $it")
        false
    }

inline fun <T, R> T.mLet(lambda: (T) -> R): R = lambda(this)

7. 仿写repeat内置函数

 repeat(10){
        println("下标是$it")
    }

 mRepeat(10){
        println("下标是$it")
    }

    10.mRepeat2{
        print("下标是$it ")

    }

private inline fun mRepeat(count:Int,lambda: (Int) -> Unit){
    for (index in 0 until count) lambda(index)
}

private inline fun Int.mRepeat2(lambda: (Int) -> Unit){
    for (index in 0 until this) lambda(index)
}

8. 仿写内置函数repeat

 val test = "zcwfeng".takeIf {
        true
        false
    }
    println(test)
    val test1 = "zcwfeng".mTakeIf {
        true
        false
    }
    println(test1)

private inline fun <T> T.mTakeIf(lambda: (T) -> Boolean): T? = if (lambda(this)) this else null

9 . 仿写内部thread函数

 thread {
        println("thread")
    }
    mThread(/*name = "dddd"*/) {
        println("mThread ${Thread.currentThread().name}")
    }

private inline fun mThread(
    start: Boolean = true,
    name: String? = null,
    crossinline runAction: () -> Unit
) {
    val thread = object : Thread() {
        override fun run() {
            super.run()
            runAction()
        }
    }
    if (start) thread.start()
    name?.let { thread.name = name }
}

crossinline 声明是防止inline的发生,防止代码错误

上一篇下一篇

猜你喜欢

热点阅读