内联函数——作用域函数

简化代码:let、run与apply在Kotlin中的巧妙应用

let

上下文对象用it引用,返回其最后一个表达式的结果。
let()用在调用链的最后面,能省点事,比如:

fun main() {
    val numbers = mutableListOf<String>("one", "tow", "three", "four")
    val resultList = numbers.map { it.length }.filter { it > 3 }
    println(resultList)
}

改成let后

fun main1() {
    val numbers = mutableListOf<String>("one", "tow", "three", "four")
    val resultList = numbers.map { it.length }.filter { it > 3 }.let { println(it) }
}

还有一种用法,就是判断对象是否为空,如果不为空,则执行Lambda中的代码,并将其上下文对象自动变成不可为空类型。示例如下:

fun main2() {
    val str: String? = "Hello"
    //processNonNullString(str)     //--这样调用有错误,因为函数要求参数不可为空,而str可为空

    //正确做法:
    val length = str?.let {
        print("let()   called on $it")
        processNonNullString(it)  //这样调用OK:“it” 以自动变为不可为空
        it.length
    }
}
fun processNonNullString(str: String) {}
//在let中一般放置相关性比较大的对上下文对象的一堆操作,包括设置属性的值、调用方法并对返回值进行运算等。

run

上下文对象用this引用,返回其最后一个表达式的结果。
run的作用有点像let,把对上下文对象相关性比较大的操作放在一起。run和let可以很自然地相互替换,比如:

class  MultiporService(val url: String, val param: Int){
    var port: Int = 8888
    fun query(str: String){}
    fun prepareRequest(): String {return "abc"}

}

val service =  MultiporService("https://google.com", 80)

val result =  service.run {
    port = 8080
    query( "${prepareRequest()} to port $port")
}

val letResult = service.let {
    it.port = 8080
    it.query("${it.prepareRequest()} to port ${it.port}")
}

//run 可以不在某个对象上调用,此时它的作用是将一堆相关的操作放在一起。当然也可以产生结果并返回给某个变量以保存下来,比如:

val hexNumberRegex = run {
    val digits = "0-9"
    val hexDigits = "A-Fa-f"
    val sign = "+-"
    Regex("s$sign]?[$digits$hexDigits]+")
}
fun testHexNumberRegex(){
    for (match in hexNumberRegex.findAll("+1234 -FFFF not-a-number")){
        println(match.value)
    }
}

apply

  • 上下文对象用this引用,返回上下文对象。
  • 在此函数Lambda中,主要对上下文对象的属性进行设置,意图是“将这些参数应用到这个对象”,所以一般用于配置对象时。
    看下面的示例代码:
val adam = KotlinBaseKnowledge.Person("Adam").apply {
    age = 32
    city = "London"
}

also

  • 上下文对象用it引用,返回上下文对象。
  • 使用also的特点是,如果从调用链中抽走also调用,不会影响调用逻辑和执行结果。
  • 此函数一般用于调用那些以上下文对象为参数的方法,比如打印上下文对象的属性值,
  • 或者将上下文对象的属性值记入日志中,而且不应该在Lambda中更改上下文对象,比如:
fun main3() {
    val numbers = mutableListOf<String>("one", "tow", "three", "four")
    numbers.also {  println(it) }.add("five")
}

with

  • 上下文对象用this引用,返回Lambda返回的值。
  • 一般在Lambda中从走上下文对象的代码
  • with的作用可以理解为“用这个对象,做点事”。当前面的函数都不大合适时,就可以考虑它了,比如:
fun main4() {
    val numbers = mutableListOf<String>("one", "tow", "three", "four")
    val firstrAndLast  = with(numbers){
        "The first element is ${this[0]} ; The Last element is ${this[this.lastIndex]}"
    }.let { println(it) }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值