Kotlin:对let,apply,run,also等作用域函数的理解

在理解这些函数之前,先从源码中摘抄出相关的代码, 放在一起,方便比较,总结规律(省略了函数的注解和部分代码, 不影响理解,了解这些代码的可以略过)

public inline fun  T.let(block: (T) -> R): R = block(this)
public inline fun  T.run(block: T.() -> R): R = return block()
public inline fun  T.apply(block: T.() -> Unit): T {
    block()
    return this
}
public inline fun  T.also(block: (T) -> Unit): T {
    block(this)
    return this
}

以下是对4个内联函数的归纳

函数和参数类型以及返回值
函数名 参数:函数作参数 返回值
let (T) -> R R
run T.() -> R R
apply T.() -> Unit T 也就是 this
also  (T) -> Unit T 也就是 this

按照参数分类:letalso可以分为一类,runapply分为一类,

1:let和also的相同点:

参数都是一个普通函数, 而且把调用者T作为一个参数传递到参数函数中,这样,在这个参数函数的作用域中就可以使用T这个参数了;

而且这个T参数还有一个默认的名称 it,it这个变量名称是可以修改的,如果不明白为啥能修改,可以把(T)-> R看成(it:T)-> R这样的普通函数,it就是个变量名称,也可以改成其他的名称(t:T)-> R或是 (a:T)-> R,不管是it,t,a,都指代的是T的实例对象。

Kotlin:对let,apply,run,also等作用域函数的理解_第1张图片 it可以修改成自己想要的变量名称,让变量意义更加明显

 

Kotlin:对let,apply,run,also等作用域函数的理解_第2张图片 also的也可以改

 

1.1: let和also的不同点:

返回值不一样,let的返回值跟它的参数函数的返回值是一致的,let的返回值是由参数函数的返回值决定的,参数函数的返回值是这个函数的最后一行或是指定的return对象

而also的返回值,指定了就是this,谁调用就返回谁,

Kotlin:对let,apply,run,also等作用域函数的理解_第3张图片

 2:run和apply的相同点

 他们的参数函数都是T.() -> 返回值 这种形式,T.() -> 返回值的意思就是 T的扩展函数是() -> 返回值, .的意思就是

// T. 的意思就是 T的
// T.apply 的意思就是 T的扩展函数,名叫apply
// T的扩展函数apply的参数, 是T的另一个扩展函数  () -> Unit
// 这个作参数的扩展函数没有参数名称, 只有一个函数的形式 () -> Unit, 意思就是没有参数,返回值是Unit
@kotlin.internal.InlineOnly
public inline fun  T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

通俗的讲就是哪个实例调用的run和apply,那么传递的参数函数就是这个实例所在类的一个扩展函数。

既然apply和作为参数的扩展函数都是属于T的, 那么在参数的扩展函数中,就可以使用this来指代这个T的实例了, 可以想一下, 原有函数也好,扩展函数也好, 都是属于同一个类,那么在扩展函数也是可以使用this, 所以在apply和run函数中都可以使用this来指代调用者, 

Kotlin:对let,apply,run,also等作用域函数的理解_第4张图片

 那么这里的this,可不可以修改呢?答案是不可以的。这里的this跟上面说的it不是一个概念,it是一个变量名称,当然可以想改就改了,this是指代调用者,比如说上面的这个例子,this就是指代的button,button就是一个变量名称,已经固定了,就不能再做更改了。

2.2:run和apply的不同点

 就是返回值类型不同了,run函数的返回值是取决于参数函数的返回值类型,所以run函数的返回值就是作为参数的扩展函数的返回值,可以是任意类型,那就看扩展函数中最后返回的是什么了

apply的返回值就不一样了,它的返回值已经固定了,就是返回this,意思是谁调用apply,就返回谁,比如上面的例子button调用了apply,那么返回的就是button。

你可能感兴趣的:(内联函数,kotlin)