分析Kotlin的 Standard.kt
代码,主要分为三部分:网络
run、with、let、also、apply
的比较takeIf、takeUnless、repeat
的使用全部的总结都源自于代码,因此最终仍是要回到代码中找到答案。app
/** * Calls the specified function [block] and returns its result. */
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R = block()
复制代码
两种写法:T.run({...})
和 T.run {}
,第二种写法是第一种的变种,当方法的最后一个参数是lambda表达式时,能够将表达式移出;less
class Main {
fun test(){
// 第一种写法
val run1 = run({
Log.d("Main", "我是内部的Run")
"Run1"
})
Log.d("Main", "我是内部的Result=$run1") //我是内部的Result=Run1
//第二种写法
val run2 = run {
Log.d("Main", "我是外部的Run")
"Run2"
}
Log.d("Main", "我是外部的Result=$run2" ) ////我是外部的Result=Run2
}
}
复制代码
/** * 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 = block()
复制代码
class Main {
fun test(){
val run = "ABCDEF".run {
substring(2) //能够在内部直接调用String的方法
}
Log.d("Main", "T.run()的值 = $run" ) //T.run()的值 = CDEF
}
}
复制代码
/** * 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 = receiver.block()
复制代码
class Main {
fun test(){
val with = with("ABCDEF") {
substring(2)
}
Log.d("Main", "with()的值 = $with" ) //with()的值 = CDEF
}
}
复制代码
/** * 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 { block(); return this }
复制代码
class Main {
fun test(){
val apply = "ABCDEF".apply {
it.substring(2)
}
Log.d("Main", "T.apply()的值 = $apply" )//T.apply()的值 = ABCDEF,值没有被改变
}
}
复制代码
/** * 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 { block(this); return this }
复制代码
class Main {
fun test(){
val also = "ABCDEF".also {
it.substring(2)
}
Log.d("Main", "T.also()的值 = $also" )//T.also()的值 = ABCDEF,值没有被改变
}
}
复制代码
/** * 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 = block(this)
复制代码
class Main {
fun test(){
val let = "ABCDEF".let {
it.substring(2) //这里须要使用it
}
Log.d("Main", "T.let()的值 = $let" ) //T.let()的值 = CDEF
}
}
复制代码
图:(图片来源于网络) ui
源码:this
public inline fun <R> run(block: () -> R): R = block()
public inline fun <T, R> T.run(block: T.() -> R): R = block()
public inline fun <T, R> with(receiver: T, block: T.() -> R): R = receiver.block()
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
public inline fun <T> T.also(block: (T) -> Unit): T { block(this); return this }
public inline fun <T, R> T.let(block: (T) -> R): R = block(this)
复制代码
从三个维度去分析:spa
run()
仍是 T.run()
)。T.also()
、T.let()
)。return this
(即:T.apply()
、T.also()
)。操做符 | 接收者(this) |
参数(it) |
返回值(result) |
典型应用场景 |
---|---|---|---|---|
run ( block: () -> R ) : R | 当前类 | / | 类R(最后一行) | |
T.run ( block: T.() -> R ) : R | 类T | / | 类R(最后一行) | |
with ( receiver: T, block: T.() -> R ) : R | 类T | / | 类R(最后一行) | |
T.apply ( block: T.() -> Unit ) : T | 类T | / | 类T | |
T.also ( block: (T) -> Unit ) : T | 当前类 | 类T | 类T | |
T.let ( block: (T) -> R ) : R | 当前类 | 类T | 类R(最后一行) |
run()
和 T.run()
比较:code
T.run()
的参数T.()
表示在其block中能够直接使用T的全部public方法,而run()
却不行;T.apply()、T.also()
和 其余几个比较:cdn
return this
,因此返回的都是以前的对象T ;T.also()
方法体中有 block(this)
,将 this
做为参数传入,因此在Lambda类型的block内部就不能再用this
获取当前的传入参数T,而要使用it
获取T,而this
实际表明的是当前所处的类;T.also()、T.let()
和 其余几个比较:对象
this
传入 block(this)
,因此T必须都要用it
来获取;/** * Returns `this` value if it satisfies the given [predicate] or `null`, if it doesn't. * * 根据当前predicate的返回值判断:若为空,则返回null,若不为空,则返回原值 * 根据上面的总结,在predicate中获取传入的参数T时要使用it,而不是this; */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null
/** * Returns `this` value if it _does not_ satisfy the given [predicate] or `null`, if it does. */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? = if (!predicate(this)) this else null
复制代码
class Main {
fun test(){
val takeif = "ABC".takeIf {
Log.d("Main", "this = $this") //this = com.example.kotlindemo.Main@f17fc13
Log.d("Main", "it = $it") //it = ABC
true //若是是false,则返回null
}
Log.d("Main", "我是takeif=$takeif" ) //我是takeif=ABC
}
}
复制代码
/** * Executes the given function [action] specified number of [times]. * * A zero-based index of current iteration is passed as a parameter to [action]. */
@kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) -> Unit) {
for (index in 0..times - 1) {
action(index)
}
}
复制代码
class Main {
fun test(){
repeat(10) {
Log.d("Main", "this = $this") //this = com.example.kotlindemo.Main@f17fc13
Log.d("Main", "$it")
}
}
}
复制代码
输出的值:blog
com.example.kotlindemo D/Main: 0 com.example.kotlindemo D/Main: 1 com.example.kotlindemo D/Main: 2 com.example.kotlindemo D/Main: 3 com.example.kotlindemo D/Main: 4 com.example.kotlindemo D/Main: 5 com.example.kotlindemo D/Main: 6 com.example.kotlindemo D/Main: 7 com.example.kotlindemo D/Main: 8 com.example.kotlindemo D/Main: 9
public class NotImplementedError(message: String = "An operation is not implemented.") : Error(message)
public inline fun TODO(): Nothing = throw NotImplementedError()
public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason")
复制代码
//Kotlin代码
class Command {
fun execute(){
TODO() //抛出异常
}
}
class Test {
val command = Command()
command.execute()// 当执行到这行代码时,就会抛出异常NotImplementedError
}
复制代码