Kotlin中的内置函数-apply、let

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

在使用Kotlin的过程中会经常用到其内置函数,包括apply,let,run,with,also,takeIf,takeUnless函数等,想要更好熟悉Kotlin,这些函数必须烂熟于心,接下来让我们来逐步了解:

apply函数

apply函数,属于内联扩展函数,其扩展了所有的泛型对象,在闭包范围内可以任意调用该对象的任意方法,并在最后返回该对象。也许看到这里你并没有太了解,接下来让我们从简单代码入手:

fun main(){
    val tips = "Hello this world"
    println("tips的字符串长度为:${tips.length}")
    println("tips的最后一个字符为:${tips[tips.length-1]}")
    println("tips全部置换大小写:${tips.lowercase()}")
}

这段函数很简单,定义一个字符串然后分别打印,对应输出结果为:

image.gif 我们加入apply函数,一般情况下,匿名函数都会持有一个it,但是apply函数没有持有it,而是持有当前this,在这里this = tips本身。我们在原函数中加入对this的引用逻辑,例如以下:

fun main(){
    val tips = "Hello this world"
    println("tips的字符串长度为:${tips.length}")
    println("tips的最后一个字符为:${tips[tips.length-1]}")
    println("tips全部置换大小写:${tips.lowercase()}")
    tips.apply { 
        println(this)
    }
}

对应的打印为: image.gif 可见,最后打印的this即是tips本身,而在apply中this又可以省略,我们修改打印到对应的apply函数中,则原代码变为以下:

fun main(){
    val tips = "Hello this world"
    println("tips的字符串长度为:${tips.length}")
    println("tips的最后一个字符为:${tips[tips.length-1]}")
    println("tips全部置换大小写:${tips.lowercase()}")
    println("---------------------------------------")
    tips.apply {
        println(this)
        println("tips的字符串长度为:${length}")
        println("tips的最后一个字符为:${this[length-1]}") //这里最外面的this不能省(Collection literals outside of annotations)
        println("tips全部置换大小写:${this.lowercase()}")
    }
}

其对应输出结果为:

image.gif 这些不难理解,所以这里我们可以说apply函数扩展的是其对象,同时还能返回生成此对象。那么问题来了,我要这函数有何用?一个语言不可能白设计一个没有作用的函数。比如我们通常声明一个文件,还要同时声明此文件一些特点时:

val file = File("C:\\HelloWorld.java")
file.setReadable(true)
file.setReadOnly()

这样修改为:

val file = File("C:\\HelloWorld.java")
file.apply { 
    setReadable(true)
}.apply { 
    setReadOnly()
}

由于apply函数能返回原对象,所以也支持链式调用。以上代码在功能作用上完全等价。

let函数

属于匿名函数类型,提供了函数式API的编程接口,将原始对象作为参数传递到表达Lamba表达式中,在闭包范围内用it指代原对象,我们还是通过实例来加深理解,先来一段简单函数:

val list = listOf(1, 2, 3, 4, 5, 6)
val first = list.first()
println(first+first)

代码不难理解,可预见输出结果为:

image.gif 再用let函数形式编写如下:

val result = listOf(1, 2, 3, 4, 5, 6).let {
    it.first()+it.first()
}
println("let结果为$result")

对应输出结果为:

image.gif 可见,let函数所返回的对象,是在函数中运行完的对象,即let函数的返回类型是根据匿名函数最后一行的变化而变化的,这是跟apply函数的一个区别,apply函数返回的永远是函数本身。例如我们添加些apply的代码,如下:

fun main(){
    val result = listOf(1, 2, 3, 4, 5, 6).let {
        it.first()+it.first()
    }
    val result2 = listOf(1, 2, 3, 4, 5, 6).apply {
        this.first()+this.first()
    }
    println("let结果为$result")
    println("apply结果为$result2")
}

对应输出结果为:

image.gif

总结

在这里我们对两个函数总结一下:

apply

1、函数返回的类型都是原泛型对象本身;

2、函数内部持有的是this,原对象本身。

Let

1、let函数所返回的对象,是在函数中运行完的对象,即let函数的返回类型是根据匿名函数最后一行的变化而变化的;

2、函数内部持有的是it。

猜你喜欢

转载自juejin.im/post/7110603299224551455