初学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 这里需要科学上网
网友评论