在使用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()}")}

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


我们加入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)}}

对应的打印为:

可见,最后打印的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()}")}}

其对应输出结果为:


这些不难理解,所以这里我们可以说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)

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


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

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

对应输出结果为:


可见,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")}

对应输出结果为:

总结

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

apply

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

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

Let

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

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