七,Kotlin常见高阶函数用法

常见高阶函数用法

基础回调

fun onItemClicked(onItemClick: (UserEntity, Int) -> Unit) {
    val list = listOf(
            UserEntity(100, "华晨宇", 30),
            UserEntity(101, "张碧晨", 31),
            UserEntity(103, "邓紫棋", 29),
            UserEntity(103, "李宇春", 32)
    )
    onItemClick(list[0], 0)
}

fun main() {
    val onItemClickListener: (UserEntity, Int) -> Unit = { item, position ->
        println("item->$item,position:$position")
    }
    onItemClicked(onItemClickListener)
}

简化版本

fun main() {
    onItemClicked { item, position ->
        println("item->$item,position:$position")
    }
}
item->userName:华晨宇,userId:100,age:30,position:0

拓展函数

kotlin支持对类的方法进行推展,拓展类未定义的方法,拓展本身支持自定义的或者android库中的类

class Student {
    val name = "s_name"
    val age = 10
}

fun Student.test() = println("name -> ${this.name} \nage -> ${this.age}")

fun main() {
    val stu = Student()
    stu.test()
}
name -> s_name 
age -> 10

方法覆盖
kotlin支持对局部变量回调的方法实现中支持对回调方法的重定义覆盖,可以使用之前的定义的参数属性(实测也无法重新定义入参,必须使用之前的入参),只需要覆盖方法实现

fun main() {
    var method = { num: Int -> println("method before $num") }
    method = { println("method after $it") }
    method(1)
}

结果输出.

method after 1

方法重载

kotlin支持方法参数定义默认值,也支持定义重载方法,比如自定义View我们一般要实现三个构造方法
kotlin支持方法参数定义默认值,也支持定义重载方法,比如自定义View我们一般要实现三个构造方法

public CustomView (Context context) {
    this(context,null);
}
public CustomView (Context context, @Nullable AttributeSet attrs) {
    this(context, attrs,0);
}
public CustomView (Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

而使用kotlin我们可以给方法定义重载的标记,下面的一个方法和上面的是等价的

class CustomView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ViewGroup(context, attrs, defStyleAttr)

泛型拓展

kotlin支持泛型的方法处理
可以看下apply和let的实现方式

public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

可以看出这两个方法中都有T.method()的处理,这里可以理解是泛型参数的拓展方法,和上面提到的是一致的。而这里的this指的是拓展方法所指定的泛型对象。
apply这里调用了方法后返回了this,同时泛型返回也是同泛型,也就是说是可以链式调用的,方法内可以使用this.xxx方法获取相应的属性,当然this也是可以省略的,直接也是可以的。

class A {
    var a: String? = null;
    var b: String? = null;
}
fun main() {
    val A = A()
    A.apply {
        this.a = "1";
        a ="1.5"; //效果是一样的
    }.apply {
        this.b = "2";
    }
    
    //甚至可以层层套娃玩
     A.apply {
        apply {
            apply { ... }
        }
    }
}

同时apply这里的block是也是一个类拓展函数,指定的是T.()的方法,其实这个就是指定将T作为方法的this上下文进行传递,然后匿名方法体实现中就可以直接通过this获取该对象了
比如我们定义一个匿名方法使用String.(),那么下面的使用是成立的,即使我们并没有指定apply的对象

fun apply2(block: String.() -> Unit) {
}
fun main() {
    apply2 {
        val lenth = this.length
        val str2 = this.substring(0, 3)
        val charArra = this.toCharArray()
    }
}

那么T.()作为匿名方法声明就可以类比上面的,就是把T作为this对象传递到匿名方法体中的。

而let则是把泛型作为it传递的,block: (T)就是传递it上下文的操作了,因为泛型都是T,block方法通过this传递了本身进去,这个就不举例了

那么把上面两个综合起来就可以看这么一个例子

fun <T, R> T.apply3(r: R, block: T.(R) -> R): R {
    return block(r)
}
fun main() {
    val str = "1234"
    str.apply3(123) {
        this.toInt() + it
        //toInt() + it 等价
    }.apply {
        print("apply result->>>$this")
    }
}

可以看出这里指定了两个泛型T和R, 然后T.(R)这里把T作为this传参,通时R作为it传参到方法体中,也就是这里可以同时使用this和it进行操作
输出结果

apply result->>>1357

那么再加一个参数呢

fun <T, R, E> T.apply4(r: R, e: E, block: T.(R, E) -> R): R {
    return block(r, e)
}

fun main() {
    val str = "1234"
    str.apply4(123, "12") { v1, v2 ->
        toInt() + v1 + v2.toInt()
    }.apply {
        print("apply result->>>$this")
    }
}

因为it只支持本身,其实本身也是一种lambda声明,多个参数直接换成多个的格式就可以了,当然this就不用处理了,只需要处理传递进来的两参数即可
输出结果

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