距离上篇Kotlin文章,应该有差很少半年时间.没别的缘由,由于,懒,并且,想产出一篇稍微质量好的博客好难. 最近在研究Python,因此最近也可能会更新一些Python的学习笔记.java
StandardKt.kotlin源码位于kotlin-stdlib-common/kotlin包下; Kotlin的扩展函数有多爽,我应该不用再描述了吧~~; 若是对kotlin扩展函数概念不清的能够找找我前面的文章;api
Kotlin提供了一个标准函数库,开发过程当中使用十分频繁,也十分方便,只能说我已经完全没法适应java开发了= =.bash
下面咱们来探究一下这个标准库的源码.标准库函数容易混淆,但源码比较简单,不要慌.app
标准库的函数基本都是内联函数 inline修饰.不知道啥是内联函数的,翻翻我前面的文章吧.less
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
复制代码
run函数在标准库有两个; 咱们直接看第二个扩展函数.入参是一个block函数,类型是一个T的扩展函数T.()->R,无参,返回值是R类型 ,也能够传入lambda表达式,记住,kotlin中万物皆对象,因此函数也是个对象; 例子:函数
/**
* 取绝对值
*/
fun Int.pow2():Double{
return Math.pow(toDouble(),2.toDouble())
}
fun testFun(){
val pow2 = "I am Zen".length.run({pow2()}) //1
Log.d(TAG,"pow2:$pow2")
}
执行testFun(),输出:pow2:64.0
在Kotlin中,若是参数是最后一个参数,{}能够提到()以后,那么上述1式子能够演变==>
val pow2 = "I am Zen".length.run(){pow2()}
Koltin中又规定,若是参数是惟一一个参数,那么()也能够省略,1式子能够演变==>
val pow2 = "I am Zen".length.run{pow2()}
一样的,若是直接传入lamda表达式,也是ok的,1式能够这样写==>
val pow2 = "I am Zen".length.run{Math.pow(toDouble(),2.toDouble())}
复制代码
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block(this)
}
复制代码
同窗们,仔细观察,let函数和run函数的区别 能够看到,T.let 入参传入的block函数,其参数是T,返回值依旧是R,block在内部调用时传入T.this;学习
/**
* 取绝对值
*/
fun Int.pow2():Double{
return Math.pow(this.toDouble(),2.toDouble())
}
fun testFun(){
val pow2 = "I am Zen".length.let { Math.pow(it.toDouble(),2.toDouble())} //1
Log.d(TAG,"pow2:$pow2")
}
执行testFun(),输出:pow2:64.0
仔细观察这个例子,能够看到它和run函数的区别在于,run传入的block函数内部直接持有的是T的引用;而let是外部传入的T的引用,在lamda中用默认用it表示;
复制代码
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return receiver.block()
}
复制代码
with函数和上述两个又很像,= =,咱们来仔细辨别一下,它又有什么不一样ui
fun testFun(){
val pow2 = with("I am Zen".length){
Math.pow(toDouble(),2.toDouble())
}
Log.d(TAG,"pow2:$pow2")
}
执行testFun(),输出:pow2:64.0
with函数有两个入参receiver:T,block函数,关于T的扩展函数,返回R
复制代码
public inline fun <T> T.also(block: (T) -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block(this)
return this
}
复制代码
also函数和let函数的区别在于,also返回的自身,入参block函数,无返回值this
val also = "I am Zen".length.also {
Math.pow(it.toDouble(), 2.toDouble())
}
Log.d(TAG,"also:$also")
输出:also:8
字符串"I am Zen".length为8,对8执行also函数,内部持有外部传入的T引用,用it表示,内部计算了it的二次幂,可是返回的仍是T自己,也便是8;因此,不难理解吧;和also函数相似的是apply函数.
复制代码
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
block()
return this
}
复制代码
apply函数十分经常使用,它能够轻松实现java的链式调用,咱们不用再那么麻烦写build模式啦; 能够看出apply函数和also函数很相识,不一样的是,对于lamda内部,apply函数中直接持有T的引用,this能够省略,因此能够直接调用关于T的全部api,而also持有的是外部传入的T的引用,用it表示,因此须要用it来调用关于T的全部apispa
@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
}
@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
}
复制代码
takeIf和takeUnless只是断言相反 因此只讲一下takeIf 这也是个十分实用的标准函数,传入的predicate断言函数,返回值Boolean,对于takeIf而言,符合条件则返回T,不然返回null,话很少说,直接看例子:
val age=17
val adultAge= age.takeIf {
it >= 18
}
Log.d(TAG,"isAdult or null:$adultAge")
输出:isAdult or null:null
predicate函数断言条件就是>=18;17执行takeIf,断言失败,返回null;
复制代码
@kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) -> Unit) {
contract { callsInPlace(action) }
for (index in 0 until times) {
action(index)
}
}
复制代码
这个标准函数能够轻松实现循环任务;time是循环的次数,action函数指定具体循环的动做
repeat(5){
Log.d(TAG,"print:$it")
}
输出:
print:0
print:1
print:2
print:3
print:4
复制代码
对于java基础者,Koltin是一门十分容易上手的语言,并且在使用了将近一年的时间后,我深深感到Kotlin给我解放的生产力.