前言
本篇文章接着上一篇文章全网最全面的由浅到深的Kotlin基础教程(六)继续进阶学习kotlin,建议看完上一篇文章,再来看本篇文章。本篇主要分析一些常用的kotlin函数源码,以及用kotlin简单实现Rxjava的几个操作符。坚持将kotlin系列的前6篇看完的,那么恭喜你再将这最后一篇看完,你就成为一名合格的kotlin开发者了。
1. kotlin标准函数源码解析
1.1 apply
源码及分析注释如下:
/*
public 访问修饰符
inline fun 内联函数
<T> 泛型定义
T.apply 泛型T的扩展函数
(block: T.() -> Unit) 输入参数为一个名为block的lambda表达式,
其中T.() 是一个泛型扩展函数,这种写法使得lambda表达式持有T的this对象,
当做固定写法来理解即可。
: T apply函数的返回类型仍然为T
*/
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
//契约函数,暂时不用关注,可以不写的
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
//执行lambda表达式的逻辑
block()
//最终仍然返回T对象本身
return this
}
1.2 also
与apply函数的意义一样,只是also函数的lambda表达式持有it,而apply函数的的lambda表达式持有this,源码及分析注释如下:
/*
public 访问修饰符
inline fun 内联函数
<T> 泛型定义
T.also 为泛型T定义扩展函数also
block: (T) -> Unit also函数中传入的参数是lambda表达式,该lambda表达式有一个T泛型的参数,返回值为空
: T also函数的最终返回值仍然为T泛型
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
//执行lambda表达式,将T泛型的this对象传入block函数,因此block通过it持有T泛型的this对象
block(this)
//不管你上面的lambda表达式干了啥,最终仍然返回T泛型对象本身
return this
}
1.3 run
源码及分析注释如下:
/*
public 访问修饰符
inline fun 内联函数
<T, R> 定义两个泛型
T.run 为T泛型定义扩展函数run
block: T.() -> R run函数有一个参数是lambda表达式,该lambda表达式通过T泛型扩展函数,拥有T泛型的this对象,返回类型为R
: R run函数的返回类型是R泛型
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
//执行lambda表达式
//因为lambda表达式拥有T泛型的this对象
//因为lambda表达式返回的是R,因此返回值由lambda表达式的最后一行决定
//return this.block() //this可以省略
return block()
}
1.4 let
与run函数的意义一样,只是let函数的lambda表达式持有it,而run函数的的lambda表达式持有this,源码及分析注释如下:
/*
public 访问修饰符
inline fun 内联函数
<T, R> 定义两个泛型
T.let 为T泛型定义扩展函数let
block: (T) -> R lambda表达式参数,输入T泛型(lambda表达式如果只有一个参数,则参数名默认为it),输出为R泛型
: R 最终返回的类型是R泛型
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
//执行lambda表达式
//因为lambda表达式传入的是this,因此lambda表达式通过it持有T泛型的对象
//因为lambda表达式输入的T,返回的是R,因此返回值由lambda表达式的最后一行决定
return block(this)
}
1.5 with
与run函数的意义一样,只是调用方式不一样而已,run是泛型扩展函数,而with是普通的函数,源码及分析注释如下:
/*
public 访问修饰符
inline fun 内联函数
<T, R> 定义两个泛型
with(receiver: T, block: T.() -> R) 这是一个普通的函数,并非扩展函数,包括两个参数,第一个T泛型的参数,第二个是lambda表达式,lambda表达式通过T泛型扩展函数,拥有T泛型的this对象,返回类型为R
: R 最终返回类型是R
*/
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
//block的最后一行是返回值
return receiver.block()
}
1.6 takeIf
源码及分析注释如下:
/*
public 访问修饰符
inline fun 内联函数
<T> 泛型定义
T.takeIf 为泛型T定义扩展函数takeIf
predicate: (T) -> Boolean takeIf函数中传入的参数是lambda表达式,该lambda表达式有一个T泛型的参数,返回值为Boolean
: T? takeIf函数最终返回的可空的T泛型类型
*/
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? <