Kotlin(run,apply)陷阱

泛型T

首先我们先看一下apply的源码

 

fun T.apply(block: T.() -> Unit): T { block(); return this }

这个泛型T可以为null,也就是说null也被赋予了apply的方法

 

null.apply{
    System.out.println("null apply")
}

在IDE里面null是没有.apply方法提示的,可是在kotlin编译里面是可以通过

null埋藏的陷阱

由于null也有apply方法,所以对一个可空的对象(A)进行apply的话,block块是被执行的。如果A的方法与全局方法有重名的时候就会调用全局的方法。

 

open class A {
    override fun toString(): String {
        return "this is A"
    }

    open fun methodPrint() {
        System.out.println("A print")
    }
}

class B {
    override fun toString(): String {
        return "this is B"
    }

    fun methodPrint() {
        System.out.println("B print")
    }

    fun print() {
        val a: A? = null
        System.out.println(a.apply {
            methodPrint()
            System.out.println("a.apply:" + toString())
        })
    }
}

输出

 

B print
a.apply:null
null

如果B还有继承关系那么就更加的隐蔽

 

class C : A(){
    override fun toString(): String {
        return "this is C"
    }

    fun print() {
        val a: A? = null
        System.out.println(a.apply {
            methodPrint()
            System.out.println("a.apply:" + toString())
        })
    }
}

输出

 

A print //此处打印的是C类的methodPrint()方法继承于A
a.apply:null
null

T泛型的扩展

利用泛型的扩展我可以封装一个nullwork方法,就是一个对象为空时执行nullblock,如果对象不为空时执行noNullblock。

 

inline fun <T, R> T?.nullWork(noNull: (T) -> R, isNull: () -> R): R {
    return this?.let {
//这里还有一个坑,就是如果block返回null还是会执行isNull()方法所以要使用return
        return noNull(it) 
    } ?: isNull()
}

总结

陷阱的关键点有2个

  1. null对象有apply方法导致null对象的apply的block块是被执行的
  2. blcok块可以调用全局方法



作者:MicroCoder
链接:https://www.jianshu.com/p/e4c026788cba
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值