1.让我们看看源码中是如何定义的
/**
* Calls the specified function [block] and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
/**
* Calls the specified function [block] with `this` value as its receiver and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
/**
* Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
}
/**
* Calls the specified function [block] with `this` value as its receiver and returns `this` value.
*/
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
/**
* Calls the specified function [block] with `this` value as its argument and returns `this` value.
*/
@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
}
/**
* Calls the specified function [block] with `this` value as its argument and returns its result.
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
看每个方法的返回值类型
apply,also返回的是它本身类型
run,with,let返回的是代码块最后一行的返回值类型
2.各个函数的应用场景
2.1 T.apply应用场景
//普通方法
fun createIntent(): Intent {
val intent = Intent()
intent.putExtra("nameFirst", "firstValue")
intent.putExtra("nameSecond", "secondValue")
return intent
}
//通过apply函数
fun createIntentByApply(): Intent =
Intent().apply {
putExtra("nameFirst", "firstValue")
putExtra("nameSecond", "secondValue")
}
//通过apply函数链式调用
fun createIntentByChainedApply(): Intent =
Intent().apply { putExtra("nameFirst", "firstValue") }
.apply { putExtra("nameSecond", "secondValue") }
2.2 T.also函数
"abc".also {
print("The String is $it") // "abc"
it.reversed()
}.also {
print("The reverse String is $it") // "abc"
it.length
}.also {
println("The length of the String is $it") // "abc"
}
2.3 T.let函数
"abc".let {
println("The String is $it") // "abc"
it.reversed()
}.let {
println("The reverse String is $it") // "cba"
it.length
}.let {
println("The length of the String is $it") // 3
}
和also函数相比返回值不同,T.let返回的是作用域最后一个对象(可和自身对象不同),
T.also返回的都是原来自身对象。
两者结合使用场景
//原始函数
fun makeDir(path: String): File {
val result = File(path)
result.mkdirs()
return result
}
//通过let和also的链式调用改进后的函数
fun makeDir(path: String) = path.let{ File(it) }.also{ it.mkdirs() }
2.4 run函数使用场景
run {
if (islogin) loginDialog else getAwardDialog
}.show()
2.5 with函数使用场景
with(webView.settings){
javaScriptEnabled = true
databaseEnabled = true
}
2.6 T.run函数使用场景
//此时run函数比上面例子要更好,因为在调用函数之前进行null检查
webView.settings?.run {
javaScriptEnabled = true
databaseEnabled = true
}