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

函数-高阶函数-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的发生,防止代码错误

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容