Kotlin专题Kotlin开发知识禅与计算机程序设计艺术

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")
    }
上一篇 下一篇

猜你喜欢

热点阅读