Kotlin系列之let 、with、run、apply、also、takeIf、takeUnless、repeat函数的使用


        相比Java, Kotlin提供了不少高级语法特性。对于一个Kotlin的初学者来说经常会写出一些不够优雅的代码。在Kotlin中的源码标准库(Standard.kt)中提供了一些Kotlin扩展的内置函数可以优化kotlin的编码。

扩展函数:let

        let扩展函数的实际上是一个作用域函数,当你需要去定义一个变量在一个特定的作用域范围内,let函数的是一个不错的选择;let函数另一个作用就是可以避免写一些判断null的操作。

var result = object?.let{//表示object不为null的条件下,才会去执行let函数体
   it.todo()  //用it代替了object
   1000 //最后一行为返回值(所以返回值类型也根据最后一行类型变化)
}

场景一: 最常用的场景就是使用let函数处理需要针对一个可null的对象统一做判空处理。
场景二: 然后就是需要去明确一个变量所处特定的作用域范围内可以使用

内联函数:with

        它是将某对象作为函数的参数,在函数块内可以通过 this 指代该对象。返回值为函数块的最后一行或指定return表达式。可以看出with函数是接收了两个参数,分别为T类型的对象receiver和一个lambda函数块

class user{
var name = "qing"
var age = 3
var phoneNum = "123"
}

var user = user()
val result = with(user) { //this代表了user,也可以省略this
    println("my name is ${this.name}, I am $age years old, my phone number is $phoneNum")
    1000 //跟let一样最后一行为返回值(类型也因为最后一行而定)
}

场景:适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可,经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上。

override fun onBindViewHolder(holder: ViewHolder, position: Int){
   val item = getItem(position)?: return
   with(item){
           holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)    
           holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
           holder.tvExtraInf.text = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
       ...   
   }
}

扩展函数:run

        run函数实际上可以说是let和with两个函数的结合体,run函数只接收一个lambda函数为参数,以闭包形式返回,返回值为最后一行的值或者指定的return的表达式。可以说跟with很相似,只是用法不同。

class user{
var name = "qing"
var age = 3
var phoneNum = "123"
}

var user = user()
val run = user?.run {//this代表了user,也可以省略this
    println("my name is ${this.name}, I am $age years old, my phone number is $phoneNum")
    1000 //跟let一样最后一行为返回值(类型也因为最后一行而定)
}

场景:和with的相同就是用法不同,那看看上面with在onBinderViewHolder使用的时候run怎么去使用

override fun onBindViewHolder(holder: ViewHolder, position: Int){
  getItem(position)?.run{   //妥妥的就是let和with的结合体
           holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)
           holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
           holder.tvExtraInf = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
       ...     
   }
   
   //最为对比把with的也粘贴过来 with
   val item = getItem(position)?: return
   with(item){
           holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)    
           holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
           holder.tvExtraInf.text = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
       ...   
   }
}

扩展函数:apply

        从结构上来看apply函数和run函数很像,唯一不同点就是它们各自返回的值不一样,run函数是以闭包形式返回最后一行代码的值,而apply函数的返回的是传入对象的本身。

//java
mSheetDialogView = View.inflate(activity, R.layout.xxx, null);
   mSheetDialogView.textView.text = "123";
   mSheetDialogView.buttonView.text = "123";
   mSheetDialogView.seek_bar.max = 10;
   mSheetDialogView.seek_bar.progress = 0;
}
//使用apply
mSheetDialogView = View.inflate(activity, R.layout.xxx, null).apply{
   textView.text = "123"  //这里持有的是this = mSheetDialogView 和 run/with一样
   buttonView.text = "123"
   seek_bar.max = 10
   seek_bar.progress = 0   //没有返回值的  他的返回就是传入的本身
}.apply{
    //继续
}

场景一:适用于run函数的任何场景,一般用于一个对象实例初始化的时候,需要对对象中的属性进行赋值,XML的View的时候需要给View绑定数据也会用到。
场景二:链式调用使用一个对象时(因为他没有返回值用同一个对象)
场景三:数据model多层级包裹判空处理的问题

扩展函数:also

        also函数的结构实际上和let很像唯一的区别就是返回值的不一样,let是以闭包的形式返回,返回函数体内最后一行的值,如果最后一行为空就返回一个Unit类型的默认值。而also函数返回的则是传入对象的本身,他持有的是it对象。

var result = object?.let{//表示object不为null的条件下,才会去执行let函数体
   it.todo()  //用it代替了object
   1000 //最后一行为返回值(所以返回值类型也根据最后一行类型变化)
}?.let{
    it.revers() //这里it已经是1000了
    2000
}?.let{
    it //这里it是2000了
}

var result = object?.let{//表示object不为null的条件下,才会去执行let函数体
   it.todo()  //用it代替了object
   1000 //最后一行为返回值(所以返回值类型也根据最后一行类型变化)
}.also{
    it.revers() //这里it还是result
    2000
}.also{
    it //这里it还是result
}

场景:适用于let函数的任何场景,also函数和let很像,只是唯一的不同点就是let函数最后的返回值是最后一行的返回值而also函数的返回值是返回当前的这个对象。一般可用于多个扩展函数链式调用(因为他没有返回值用同一个对象)

扩展函数:takeIf

理论上你可以把代码中的所有 if 替换成 takeIf(虽然不推荐)
首先takeIf使用如下:

var user = User()
user.takeIf { user.age == 1 } 
//如果takeIf中表达式为ture时返回值为this也就是本身
//如果takeIf中表达式为false时返回值为null

那有人问了返回null有什么用,那就需要我们进行配合使用了,比如:

user.takeIf { user.age == 1 } ?: return false
// ?:Elvis操作符: 当前面时null时返回后面的表达式

注意:因为返回时this所以takeIf也可以进行链式调用

user.takeIf { user.age == 1 }?.let{
        it
       //操作。操作返回的是this = user
       //那么这里it是指代的上面的 = user
}

扩展函数:takeUnless

        与 takeIf 相反, 如果判断表达式为 true 则返回 null,false 返回对象本身。

循环函数:repeat

        repeat() 其实是kotlin中的一个为我们封装好的函数,代表这个括号里面的代码需要被执行多少次,这里我传入了10代表里面的代表需要被循环10次,里面的it为这个函数提供的变量,我们直接使用就可以,他可以显示目前为止程序被执行到了第几次

repeat(10){
        print(it);
    }
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值