Kotlin作用域函数let、with、run、apply、also

Kotlin标准库中的letwithrunapplyalso这五个函数相当有意思。它们的实现非常简单,区区两三行,却直击了Java的若干痛点。
Kotlin对它们的定位是scope functions。这是什么意思呢?
我理解scope functions是指这些函数可以通过新的作用域操作对象,避免引入临时变量或一次性函数污染原作用域。
下面简要分析下这几个函数。

let

函数结构

object.let{
   //在函数体内使用it替代object对象去访问其公有的属性和方法
   it.todo()
   ...
}

//另一种用途 判断object为null的操作
//表示object不为null的条件下,才会去执行let函数体
object?.let{
   it.todo()
}
适用的场景
  • 使用let函数处理需要针对一个可null的对象统一做判空处理(常用)

  • 需要去明确一个变量所处特定的作用域范围内可以使用

例子
  • 不使用let

mTextView?.textSize(...)
mTextView?.setTextColor(...)
mTextView?.background(..)
  • 使用let

mTextView?.let{
        it.textSize(...)
        it.setTextColor(...)
        it.background(..)
}
特点
  • 函数体内使用it指代当前对象
  • 返回值为函数块的最后一行或指定return表达式
  • 可以在调用let之前判空处理

with

函数结构

 with(object){
   //todo
 }
适用的场景
  • 适用于调用同一个类的多个方法时,可以省去类名重复,直接调用类的方法即可(经常用于Android中RecyclerView中onBinderViewHolder中,数据model的属性映射到UI上)
例子
  • 不使用with

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
         itemView.shop_tv_edit.setOnClickListener(listener)
         itemView.shop_tv_insert.setOnClickListener(listener)
         itemView.shop_tv_show.setOnClickListener(listener)
         itemView.shop_tv_hide.setOnClickListener(listener)
}
  • 使用with

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
        with(itemView) {
            shop_tv_edit.setOnClickListener(listener)
            shop_tv_insert.setOnClickListener(listener)
            shop_tv_show.setOnClickListener(listener)
            shop_tv_hide.setOnClickListener(listener)
        }
}
特点
  • 在函数块内可以通过 this 指代当前对象
  • 返回值为函数块的最后一行或指定return表达式

run

函数结构

object.run{
//todo
}
适用的场景
  • 适用于let,with函数任何场景
例子
  • 不使用run

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 = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews" 
   
   }
}
  • 使用run

override fun onBindViewHolder(holder: ViewHolder, position: Int){
   
  getItem(position)?.run{
      holder.tvNewsTitle.text = StringUtils.trimToEmpty(titleEn)
       holder.tvNewsSummary.text = StringUtils.trimToEmpty(summary)
       holder.tvExtraInf = "难度:$gradeInfo | 单词数:$length | 读后感: $numReviews"
   }
}
特点
  • 函数体内使用this指代当前对象或者省略
  • 返回值为函数块的最后一行或指定return表达式
  • 可以在调用run之前判空处理
  • run函数是let,with两个函数结合体,适用于let,with函数任何场景。准确来说它弥补了let函数在函数体内必须使用it参数替代对象,在run函数中可以像with函数一样可以省略,直接访问实例的公有属性和方法,另一方面它弥补了with函数传入对象判空问题,在run函数中可以像let函数一样做判空处理

apply

函数结构

object.apply{
//todo
}
适用的场景
  • 适用于run函数的任何场景,一般用于初始化一个对象实例的时候,操作对象属性,并最终返回这个对象

  • 动态inflate出一个XML的view的时候需要给view绑定数据

  • 一般可用于多个扩展函数链式调用

  • 数据model多层级包裹判空处理的问题

例子
  • 不使用apply

val wgDialog = WGDialog(this@ShopStuffActivity)
    wgDialog.message = "该页面尚未保存,是否返回?"
    wgDialog.btnLeft = "取消"
    wgDialog.btnRight = "确定"
    wgDialog.addListener(WGDialog.Item.RIGHT, object:   WGDialogInterface.OnClickListener{
          override fun onButtonClick(which: Int, isCheck: Boolean) {
               finish()
          }
    })
    wgDialog.show()
  • 使用apply

WGDialog(this@ShopStuffActivity).apply {
   message = "该页面尚未保存,是否返回?"
   btnLeft = "取消"
   btnRight = "确定"
   addListener(WGDialog.Item.RIGHT, object: WGDialogInterface.OnClickListener{
          override fun onButtonClick(which: Int, isCheck: Boolean) {
                  finish()
          }
     })
  }.show()
特点
  • 函数体内使用this指代当前对象或者省略
  • 返回的值是对象本身(this)
  • 可以在调用apply之前判空处理

also

函数结构

object.also{
//todo
}
适用的场景
  • 适用于let函数的任何场景,唯一的不同是also返回的值是对象本身(this),一般可用于多个扩展函数链式调用
例子
  • 不使用also

mTextView?.textSize(...)
mTextView?.setTextColor(...)
mTextView?.background(..)
  • 使用also

mTextView?.also{
        it.textSize(...)
        it.setTextColor(...)
        it.background(..)
}
特点
  • 函数体内使用it指代当前对象
  • 返回的值是对象本身(this)
  • 可以在调用also之前判空处理

总结

函数名函数体内使用的对象返回值
letit函数块的最后一行或指定return表达式
withthis或省略函数块的最后一行或指定return表达式
runthis或省略函数块的最后一行或指定return表达式
applythis或省略this
alsoitthis

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值