我按照返回值做了区分, 这样好理解, 如果标准函数返回的自己, 则我们可以做属于自己的的链式调用, 如果返回的是别人, 可以做别人的链式调用, 如果函数类型参数有扩展, 则可以使用
this
let
函数let
函数把this
当作参数传递给lambda
的参数, 然后返回lambda
的返回值
val first = listOf(1, 2, 3).first()
val res = first * first
println(res)
println(listOf(1, 2, 3).first().let { it * it })
public inline fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
with
函数(不是扩展函数)val with = fun MutableList<Int>.(): Int {
this[0] += 1
return this[0]
}
fun main() {
val list = with(listOf(1, 2, 3)) {
this.map {
it + 1
}
}
println(list)
println(mutableListOf(1, 2, 3).with())
// with(listOf(1, 2, 3))
}
with
函数第一个参数是传递接收者, 第二个参数传递的是 匿名扩展函数类型
上面的代码我写了个匿名扩展函数变量, 可以代替 with
函数, 而且使用方式很像
kotlin
源码:
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
block: T.() -> R
的使用方法有两种, 第一种是block(this)
这种方式调用, 还有一种就是this.block()
的方式调用, 这两种都行, 第一种是我们跳过编译器主动传递this
进去, 第二种是 编译器主动将接收者当作 参数 传递进去
with
的使用场景const val letter: String = "abcdefghijklmnopqrstuvwxyz"
fun alphabet01(): String {
val stringBuilder = StringBuilder()
letter.forEach { stringBuilder.append(it.uppercaseChar()) }
stringBuilder.append("\nNow I know the alphabet!")
return stringBuilder.toString()
}
使用 stringBuilder
对象本身数量有点多的时候, 可以考虑使用 with
fun alphabet02() = kotlin.with(StringBuilder()) {
letter.forEach { if (it in 'a'..'z') {
// append(it.minus('a').plus('A'.code).toChar())
append(it.uppercaseChar())
} }
append("\nNow I know the alphabet!")
toString()
}
我们还可以使用 buildString
, 它底层使用的还是 StringBuilder
所以这样可以这样:
fun alphabet03() = buildString {
for (c in letter) {
append(c.uppercaseChar())
}
append("\n" +
"Now I know the alphabet!")
}
它在返回的时候, 返回的是 String 类型
StringBuilder().apply(builderAction).toString()
run
扩展函数val s = File("""D:\test.txt""").run {
if (canRead()) reader().buffered().use { it.readText() } else null
}
println(s)
public inline fun <T, R> T.run(block: T.() -> R): R {
return block()
}
use
扩展函数主要用于文件流操作, 帮助添加
try catch finally
val s = FileReader("""D:\test.txt""").buffered().use {
it.readText()
}
println(s)
also
扩展函数also
支持链式调用
使用方法:
val file = File("""D:\test.txt""").also {
println(it.name)
}.also {
// println(it.readLines())
println(it.readText())
}
kotlin
also
底层函数:
public inline fun <T> T.also(block: (T) -> Unit): T {
block(this)
return this
}
taskIf
扩展函数如果满足 taskIf
的条件(为 true
), 则返回 this
, 否则 返回 null
val file = File("""D:\test.txt""").takeIf {
it.canRead() && it.canWrite()
}
println(file)
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
return if (predicate(this)) this else null
}
很简单, 函数参数 predicate
, 使用 predicate
函数 , 传递 this
进入函数体中执行, 然后返回 boolean
, 同 Boolean
判断 如果 为 true
则返回 this
, 否则返回 false
这个也可以链式调用, 但是需要判断是否 可空 比较麻烦一点
taskUnless
扩展函数如果表达式不满足条件, 则返回 this
, 否则返回 null
val file = File("""D:\test.txt""").takeUnless {
it.isDirectory
}
println(file)
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
return if (!predicate(this)) this else null
}
注意上面
takeIf
和takeUnless
都返回的可空类型,T?
withLock
线程锁扩展函数val l: Lock = ReentrantLock()
l.withLock {
// ...........
}
public inline fun <T> Lock.withLock(action: () -> T): T {
lock()
try {
return action()
} finally {
unlock()
}
}
用法:
val file1 = File("""D:\test.txt""")
file1.setWritable(true)
file1.setReadable(true)
file1.setExecutable(true)
val file2 = File("""D:\test.txt""").apply {
setWritable(true)
setReadable(true)
setExecutable(true)
}
应用场景:
apply 类似于一个配置函数, 用于配置接收者, 然后再返回配置好的接收者
解析:
public inline fun <T> T.apply(block: T.() -> Unit): T {
block()
return this
}
把接收者作为 T 带入 File.apply(block: File.() -> Unit): File
, 我们解析一下:
这里需要注意一点, block 是 lambda 表达式, 把 lambda 表达式传递进另一个函数体内部, lambda就可以访问表达式外部函数体作用域能访问的所有东西, 这是
闭包
闭包
就是能够读取其他函数内部变量的函数, 或者叫 定义在一个函数内部的函数, 这样函数体内部能够访问函数体外部的, 本质上,闭包是将函数内部和函数外部连接起来的桥梁
然后就能看到了
不推荐, 这种方式查询出来的东西太多了, 不能够限定只查询 extension
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TIpa5UMp-1656299586587)(https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/233ee3a7759c4082b202ab0118822dc9~tplv-k3u1fbpfcp-watermark.image?)]
将函数内部和函数外部连接起来的桥梁
然后就能看到了
[外链图片转存中…(img-n0PcYruw-1656299586585)]
[外链图片转存中…(img-DuPnalZq-1656299586586)]
不推荐, 这种方式查询出来的东西太多了, 不能够限定只查询 extension
[外链图片转存中…(img-TIpa5UMp-1656299586587)]