在使用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。