一、apply
apply可以认为是配置函数,对apply调用者进行配置,内部隐私调用this,函数最终返回调用者对象
//函数源码
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
//调用示例
val file = File("hello.txt").apply {
this.setReadable(true)
setWritable(true)
setExecutable(false)
}
二、let
let返回lambda表达式的结果
//源码
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
//调用示例
val result = listOf<Int>(1,2,3).first().let {
it*it
}
println(result)
// output 9
三、run
run函数返回lambda表达式的结果,同时包含隐式调用this, 此外run函数可以执行函数引用
fun checkLong(target:String) = target.length>=10
val result = "The people's Republic of China.".run{
checkLong(this)
}
//run函数调用函数的引用
val result2 = "The people's Republic of China.".run(::checkLong)
//run函数的链式调用
"The people's Republic of China."
.run(::checkLong)
.run(::println)
四、with
with是run函数的变体,需要在调用的时候传递一个参数
val result = "The people's Republic of China.".run {
length>=10
}
val result2 = with("The people's Republic of China."){
length>=10
}
五、also
also和let函数功能相似,可以把接收者作为值传递给lambda,不同的是,also返回接收者对象,let则返回的是lambda的结果,这样also可以变相实现基于原始接收者的链式调用
//源码
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
}
//变相链式调用
File("a.txt").also {
println("start ${it.name}")
}.also {
it.readText()
}.also {
println("end ${it.name}")
}
六、takeIf
takeIf函数需要判断lambda中提供的条件表达式的结果,当结果为true,从takeIf函数返回接收者对象;当结果返回false,则返回null,作用类似if语句。
//源码
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (predicate(this)) this else null
}
//调用示例
"hello".takeIf {
!it.isNullOrEmpty()
}
?.forEach {
println(it)
}
这里引出另一个关键字takeUnless,当lambda中条件表达式返回false的时候,返回结果,否则返回null,可以理解双重否定表示肯定,详见源码
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
contract {
callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
}
return if (!predicate(this)) this else null
}
网友评论