Kotlin之作用域函数let、also、with、run、apply

1.let
@kotlin.internal.InlineOnly
public inline fun  T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

作用:调用某个对象的let函数,则将该对象为函数的参数,在函数块中用it替代该对象。返回值为函数块的最后一行。

适用场景:(1)处理一个可null对象,统一判空处理;(2)明确一个变量所处特定作用域范围内可用

data class User(val name: String, val age: Int)

private var user: User? = null

fun main() {
//    user=User("bestchangge",18)
    user?.let {//①判断user不为null的条件下才会执行let函数体
       //②it代表user对象,通过it可以访问其属性和方法
        println("姓名:${it.name} —— 年龄:${it.age}")
    }
}
2.also
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun  T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

also适用于let的任何场景,与let不同的是返回了this(表示对象本身),可以对传入的对象进行操作,可以用于链式调用

data class User(var name:String="",var age: Int=0)

private var user: User? = null

fun main() {
    user=User()
    user?.also {
        it.name="bestchangge"
        it.age=18
    }
}
3.with
@kotlin.internal.InlineOnly
public inline fun  with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

作用:非扩展函数,将对象作为函数的参数,在函数块内可以通过this指代该对象,返回函数最后一行

适用场景:同一个对象多个方法时,可以省去类名重复,直接调用方法即可。

data class User(val name: String, val age: Int)

private var user: User? = null

fun main() {
    user=User("bestchangge",18)
    with(user!!){
        //可以省去对象名user
        println("姓名:${name} —— 年龄:${age}")
    }
}
4.run

扩展函数方式 T.run{}

@kotlin.internal.InlineOnly
public inline fun  T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

非扩展函数run{}

@kotlin.internal.InlineOnly
public inline fun  run(block: () -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

run函数可以说是let和with的结合体,弥补了let函数在函数块内必须用it替代对象,又弥补了with函数传入对象判空的问题。

user?.run{
    println("姓名:${name} —— 年龄:${age}")
}
5.apply
@kotlin.internal.InlineOnly
public inline fun  T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

可以看到apply返回了this(对象本身),可以将apply包含到调用链中,这唯一一点和run函数不同。

apply函数适用于:对象初始化的时候,需要对对象中的属性进行赋值。

data class User(var name:String="",var age: Int=0)

private var user: User? = null

fun main() {
    user=User()
        user?.apply {
        name="aa"
        age=81
        }
}
6.小结

(let)null场景,特定作用域 —> 升级版(also)返回this,可操作传入的对象

(with)省去类名直接调方法

—>升级版(run)let和with结合体,省去类名和传入对象判空的问题

—>升级版(apply)返回对象本身,可以操作对象

另:takeIf满足条件返回this,否则返回null;takeUnless不满足条件返回this,否则返回null

你可能感兴趣的:(Kotlin之作用域函数let、also、with、run、apply)