Kotlin作用域函数场景对比
2019-11-20 本文已影响0人
gaom明
先来看一段代码
fun alphabet(): String {
val result = StringBuilder()
for (letter in 'A'..'Z') {
result.append(letter)
}
result.append("\nNow I know the alphabet!")
return result.toString()
}
"result."频繁出现 如何去掉繁琐的出现的变量代码
我们可以在赋值时增加代码块 {return with(对象){this.就可以调用了,
当然也就可以省略this.了}}
fun alphabet(): String {
val result = StringBuilder()
return with(result) {
for (letter in 'A'..'Z') {
append(letter)
}
append("\nNow I know the alphabet!")
this.toString()
}
}
再进一步 直接把外层代码块也干掉,
with返回的是其中最后一行的值 所以可以推导出类型 也可以省略
fun alphabet() = with(StringBuilder()) {
for (letter in 'A'..'Z') {
append(letter)
}
append("\nNow I know the alphabet!")
toString()
}
T.apply
//T.apply源码
//首先apply声明成泛型T的扩展函数,就是说任何类型皆可调用它
//唯一参数是一个函数,这个函数也是泛型T的扩展函数,匿名,没有入参没有返回值
//最后apply返回T
//函数体中先调用了传入的参数,也就是函数,T的扩展函数block
public inline fun <T> T.apply(block: T.() -> Unit): T {
block() //由于block的类型是泛型T的扩展函数,所以在block内部可以直接调用T的this.append等其他public方法
return this //返回this , 也就是泛型T本身
}
//示例
fun alphabet() = StringBuilder().apply {//作为最后一个也是唯一参数,lambda可提取到括号外声明
for (letter in 'A'..'Z') {
append(letter)//省略this.
}
append("\nNow I know the alphabet!")
}.toString()//apply返回值就是T,也就是StringBuilder, 当然也就可以调用起toString方法
with
//with源码
//接收俩个参数,1是泛型T 2是泛型T的一个扩展函数(无入参,返回值为泛型R)
//with调用第一个参数T的block方法,block也就是with的第二个参数,并把block的返回值作为自己的函数返回值
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
return receiver.block()
}
//示例
val b1: Boolean = with("123") {//lambda(省略了参数声明和箭头,并且lambda作为with的第二个实参可以拿到括号外声明)
//lambda作为泛型T的扩展函数,所以其作用域在T(String类)内部,也就是this即为"123"
println(this)
this.toBoolean()//可以省略this.调用,其返回值是lambda的返回值,也是with的返回值
}
run
//源码
public inline fun <R> run(block: () -> R): R {
return block()
}
//示例
val b2: Boolean = run {
println("")
"123"
}.toBoolean()
//实用性场景分析 : 简化部分相同操作,如下两个变量都调用了show方法
run {
if (firstTimeView) introView else normalView
}.show()
T.run
//T.run源码
public inline fun <T, R> T.run(block: T.() -> R): R {
return block()
}
//示例
val b3: Boolean = "123".run {
println(this)
toBoolean()//省略this.
}
T.let
//T.let源码
public inline fun <T, R> T.let(block: (T) -> R): R {
return block(this)
}
//示例
val b4: Boolean = "123".let { a ->
//a替换it 也可省略
println(a)
a.toBoolean()
}
//操作符配合使用
nullVal?.let {
println("[nullVal] not null code block")
} ?: run {
println("[nullVal] null code block")
}