Kotlin编程Kotlin

Kotin边学边用:apply / with / run / a

2018-07-24  本文已影响24人  朱和

Key Takeaways(划重点)

背景

Kotlin是一门简洁、高效的语言,为此,它的ifwhenthrow都支持expression而非Java的纯Statement,其官方的Coding Conventions也有如下建议:

Prefer using an expression body for functions with the body consisting of a single expression.

与此同时,Kotlin更是提供了5个类似的、便于在对给定对象的上下文下执行区块代码的函数(to execute a block of code in the context of a given object):T.apply, with, run/T.run, T.also, T.let。官方也提供了这5个函数的使用建议:Using scope functions apply/with/run/also/let。这个官方建议相对而言比较高屋建瓴或者说比较抽象,具体使用的时候还是得猜/试/蒙,这和我们严谨的程序员作风严重不符。

纯接口分析

先撇开run的其中一个光杆变体(其实也没分析它的必要),直接对5个函数定义进行分析:

T.also((T) -> Unit): T
T.apply(T.() -> Unit): T

T.let((T) -> R): R
T.run(T.() -> R): R
with(T, T.() -> R): R

直观的结论就是:

上述的差异可以通过简单的两句顺口溜陈述:

简单的分词来帮助记忆(参考下表):

it分区 this分区 返回值
let it run with dream
it also applies (apply) to self

所以技术层面得到的这两句顺口溜应该能清晰的让我们知道这5个函数的差异了,剩下的就是如何把这些函数用在适合的场景了。

适用场景差异分析

首先清晰的返回值差异已经可以决定是走第一句还是第二句顺口溜,剩下的就是确定是走参数 it 还是 扩展函数 this

这个其实通过代码就能很清晰的看出结论来:(取自Kotlin官方样例

    // Nice.
    val foo = createBar().also {
        currentBar = it                    // Accessing property of Baz
        observable.registerCallback(it)    // Passing context object as argument
    }
    
    // Yack!
    val foo2 = createBar().apply {
        currentBar = this                    // Accessing property of Baz
        observable.registerCallback(this)    // Passing context object as argument
    }
    // Nice.
    val foo: Bar = createBar().apply {
        color = RED    // Accessing only properties of Bar
        text = "Foo"
    }
    
    // Yack!
    val foo2: Bar = createBar().also {
        it.color = RED    // Accessing only properties of Bar
        it.text = "Foo"
    }

很明显,参数形式的it.color = RED肯定不如扩展函数的color = RED简洁。

this的话,由于Kotlin支持多种scope,因此this的出现会让人比较难以理解到底指向的是哪个。一般而言,扩展函数中如果出现了显式的this调用,那就不如改成参数(it)的方式更容易理解的。

通过代码的分析,我们可以得出:有显式使用this时,请换成it调用

nullable的分析

直接看代码吧:

    // Nice.
    person?.run {
        awarded = true
        award = "Big Stuff"
    }

    // Yack!
    with(person) {
        this?.awarded = true
        this?.award = "Big Stuff"
    }

对于withnullable的处理就远不如其他几个来的方便了。

所以:可为null时别和with搭档

汇总下来就是:

希望这四条顺口溜能对你有所帮助,喜欢的话点个赞吧👍!

更多Kotlin的实用技巧,请参考《Kotlin边用边学系列

参考资料

上一篇 下一篇

猜你喜欢

热点阅读