上期我们学了函数的一些高级用法和字符串的基础操作,还记得什么是函数的函数吗?我们说匿名函数就是lambda表达式,然后我们将lambda函数当成一个参数传给kotlin的参数,那么就是一个函数的函数,就像是C语言里面的函数指针,然后是字符串的length,replace替换操作,其实就是我们手动替换了一些字符,增加阅读难度。
那么这一期我们接着聊函数,不过今天我要带来的可不是一般的函数,他们都是匿名却又各不相同,它们叫内置函数,需要注意的函数有两个,一个是返回值类型是否变化,一个是it或者this,名称不一样,但都是代表的是对象本身:
1、apply函数
这也是一个匿名函数,大家都知道在匿名函数里面会有一个it代表对象本身,而在apply函数里没有,他只有一个this,而且还是可以省略的,编译器会自动帮你填写的对象,同样代表的是对象本身:
//2.2 apply 内置函数,就是this的用法
val file = File("G:\\余额.txt")
file.apply {
//设置可修改,因为this可省略
setExecutable(true)
}.apply {
//因为返回值也是对象本身,所以我们可以链式调用
setReadable(true)
}.apply {
//将文本一行打印
println(readLines())
}
而且返回值也是对象本身,也就是这里的file,所以它就支持链式调用;apply内置函数适用在一个对象需要调用很多不同的函数是,我们可以通过apply来省略一些繁琐的代码,简化代码;
2、let函数
我们之前就已经学过这个函数了,主要就是it的使用,和apply的it一样,但是不一样的是apply不管最后一行代码是什么,返回值都是对象本身,而let函数的返回值就是最后一行:
//2.3 let 内置函数,含有it的使用
val list = listOf(1,2,3,4,5)
val value = list.let {
val value = it.first()
value + value
}
println(value)
这里介绍一个函数的简化写法:
//普通方式的函数写法
fun methods1(info: String?): String{
return if(info == null) "你传给我的是空值" else "不是空值,可以继续"
}
//其实这个还有简化写法
/*这两个函数的结果是一样的*/
fun methods2(info: String?) = if(info == null) "你传给我的是空值" else "不是空值,可以继续"
前者是真的在写函数,但是后者就像在赋值,但是效果都是一样,后者给人的感觉就是使用一个匿名函数给methods2 赋值;当然这两者的效果是一样的。
3、run内置函数
这个函数的特殊之处就在于含有this却又具有最后一行的返回值,就像是前面两个函数到的一种结合:
//2.5 run内置函数的使用
/*
* 和前面的不同,run是前面两着的集合,具有最后一行的
* 返回值,却又不具有it,具有this
* 在这个方法里面可以使用匿名和具名来执行一些操作*/
val str = "Tony"
//匿名实现一系列封装事件,上一个run的返回值会变为下一个的this
str
.run { if(length > 3) true else false }
.run { if (this) "Tony is coming" else "error person" }
.run { "【$this】" }
.run { println(this) }
//使用引用符号来调用
str
.run(::islong)
.run(::showWelcome)
.run(::mapstr)
.run(::println)
/*
具名实现,上一个的返回值变为下一个函数的参数
如果加上了fun写函数表示是一个普通函数,我们想要有返回值就一定要写return
还有返回值类型,是要遵循规范的
* */
fun islong(msg : String): Boolean{
return if(msg.length > 3) true else false
}
fun showWelcome( flag: Boolean): String{
return if (flag) "Tony is coming" else "error person"
}
fun mapstr(msg: String): String{
return "【$msg】"
}
有一个特点就是,在我们使用具名函数引用的时候,程序会将上一个run的返回值传给下一个具名函数的参数,前面的let其实也可以做到,不过它使用的是it,其实就是一个名称的区别,重点还是看返回值;
这里注意一点,在我们写一个普通函数的时候一定要注意规范,没有匿名函数那么简便,它不给你推断返回值的,也不是以最后一行为返回值,而是以return后面的为返回值;
4、with内置函数
这个函数run的性质基本一样,都是含有this,然后返回的是最后一条语句,但是用法是不一样的,也具有匿名和具名函数调用:
//3.1 with内置函数,这个函数性质是和run一样的
/*
* 具有this和返回最后一行返回值
* 也具有匿名和具名函数两种
* */
val name4 = "Tony"
//具名函数调用
val r1 = with(name4,::getlength)
val r2 = with(r1,::showlength)
with(r2,::println)
//匿名函数调用
with(with(with(name4){
this.length
}){
"This name has $this words"
}){
println(this)
}
//with的具名函数
fun getlength(str: String): Int{
return str.length
}
fun showlength(number: Int): String{
return "This name has $number words"
}
具名函数的调用并没有那么灵活,只是每次的调用的返回值都是通过一个变量接受的,匿名函数的用法就像是包菜一样一层层套上去的,并不想run的链式调用;
5、also内置函数
这个函数和apply差不多,想对他不具有this,但是他有it,返回值和apply一样,永远都是对象本身,支持链式操作:
//3.2 also 函数,和apply差不多
/*
* also函数与apply不同的是apply是持有的this,而
* also持有的是it,它们都是常用在file操作中,调用
* 的返回值永远都是对象本身
* */
val file2 = File("G:\\余额.txt")
file2.also{
it.setWritable(true)
}.also{
it.setReadable(true)
}.also{
println(it.readLines())
}
一般使用在对象不变的时候,像file操作
6、takeif和 takeunless
这个函数是使用在我们需要数据验证的时候,如果takeif后面的函数体返回值为true就会返回一个true否则返回一个null,而takeunless就是反过来的:
//3.3 takeif 和 takeunless
/*
* 这两个函数其实就是相反的关系,其他都是一样的
* 不过有时候我们需要用来事物的反方面
* */
//模拟登陆
val name5 = showlogin("Tony", "123456")
println("$name5,尊贵的用户,欢迎回来")
//takeif和takeunless的函数
public fun showlogin(username: String ,Pwd: String): String ?{
return if(!(username.isNullOrBlank().takeUnless { true }?: true))
"不合法的用户"
else
username.takeIf{ checklogin(username,Pwd) }?: "登录成功"
}
private fun checklogin(username: String ,Pwd: String): Boolean{
return if(username == "Tony" && Pwd == "123456") true else false
}
这里有两个函数,一个是判断用户名和密码是否一致的后台函数,如果一直返回true否则返回false,这样的话我们在前段函数里面在数据合法的情况下面进行调用就可以实现数据的验证;一般是需要配合判断非空用的;
所以总结一下这几个内置函数,就是对于返回值是最后一行还是永远是对象本身,持有的是it还是this的各种搭配,apply,let是两个不一样的内置函数,返回值和持有对象都不一样,而且我们一般使用apply进行链式操作,一般在文件操作中,其他的只是这两者的随意组合罢了;
好了,那么这一期就到这,我们函数就先告一段落,快去试一试吧!