美文网首页
let also run with apply选择太多?教你怎么

let also run with apply选择太多?教你怎么

作者: 叛逆的曾小砂 | 来源:发表于2019-01-17 00:59 被阅读8次

    初学kotlin ,kotlin 提供了几个标准函数:let also run with apply ,但发现,这几个东西什么鬼,选择太多,一时间不知道选哪个好,

    俗话说:
       底裤选得好,老公回家早!
    

    咳咳,该进入正题了,来看看一下源码先....

    public inline fun <R> run(block: () -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return block()
    }
    public inline fun <T, R> T.run(block: T.() -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return block()
    }
    public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return receiver.block()
    }
    public inline fun <T> T.apply(block: T.() -> Unit): T {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        block()
        return this
    }
    public inline fun <T> T.also(block: (T) -> Unit): T {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        block(this)
        return this
    }
    public inline fun <T, R> T.let(block: (T) -> R): R {
        contract {
            callsInPlace(block, InvocationKind.EXACTLY_ONCE)
        }
        return block(this)
    }
    

    卧槽,看不懂啊,源码果然高深,一般人还真难看的懂。。。
    (不过还是得说明,这里的T是泛型,R也是泛型,不过是返回新的泛型,不同于T,这是两个不同的泛型)

    在选择函数的时候,可以根据三个条件来选择使用哪个函数?

    1、是否返回函数本身,就是👆上面的:T,还是:R

    从源码可以看出,就apply 和also 是返回本身T的
       T.apply(block: T.() -> Unit): T {}
       T.also(block: (T) -> Unit): T {}
    其他返回一个已变的R
    

    2、是否需要扩展函数,如是否需要null check

    返回的都是R

    with 和 run 都是 从T变成R,然后返回R,
    两个都是使用This(this一般可以省略不写)
    fun <T, R> T.run(block: T.() -> R): R {}
    fun <T, R> with(receiver: T, block: T.() -> R): R {}
    
    如果webview.settings可能为null,如下
    // So bad
    with(webview.settings) {
          this?.javaScriptEnabled = true
          this?.databaseEnabled = true
       }
    }
    // Nice.
    webview.settings?.run {
        javaScriptEnabled = true
        databaseEnabled = true
    }
    

    但是在adapter 中,我们可以使用with来bindView

    with(user){
      iHolder.itemView.tvName.text = name
    }
    省略user.name 的use
    

    需要扩展的有:T.run(), T.let()
    不需要的有:run(),with(T)

    3、是使用this 还是it 作为传入的参数

    this 类有 with(T),T.run,T.apply()
    it 类有 run() ,T.let(),T.also()
    我们就使用返回本身的那两个函数apply 和also 来作为例子
    apply 使用 this
    also 使用 it

    class User( var name:String?=null, var age:Int = 0)
    fun test(){
        val user = User("小明",21)
        user.also {
          println("test-user $it.age ")   // User@9ae5a81.age 
            it.age = 20
          println("test-user $it.age ") // User@9ae5a81.age 
        }
        user.also { ur ->
            println("test-user $ur.age ")   // User@9ae5a81.age 
        }   【是的,it 可以改名字】
    
        user.apply {
            println("test-user $age ") // 21岁
            age = 23
            println("test-user $age ") // 23岁
        }
    }
    

    可以从上面看出,使用this 和使用it 作为参数,是怎么样的效果,一个返回的是内容,一个返回的是对象地址,所以,如果是展示内容,选用this,如果是操作之类,选it

    突然发现,run有两个啊,一个是run() ,一个是T.run()除了返回都是R,其他都是相反的,run() 使用it ,不可扩展功能,T.run() 使用this,可扩展功能

    划重点!!必背

    是否返回本身 —— 是 ——  用this T.apply()      用 it  T.also()
    |
    否
    |
    需要扩增函数 —— 是 ——  用this T.run()        用 it  T.let()
    |
    否   ————————————  用this with()          用 it  run()
    
    返回R 返回R 返回本身T
    可扩展 不扩展
    使用this T.run() with(T) T.apply()
    使用it T.let() run() T.also

    在这里借用一下大神的图,对的有点懒
    https://medium.com/@elye.project/mastering-kotlin-standard-functions-run-with-let-also-and-apply-9cd334b0ef84 这里需要科学上网

    image.png

    相关文章

      网友评论

          本文标题:let also run with apply选择太多?教你怎么

          本文链接:https://www.haomeiwen.com/subject/huavdqtx.html