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

简介: 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之前判空处理

总结

1688274402327.png

相关文章
|
20天前
|
Java 调度 Android开发
Android经典实战之Kotlin的delay函数和Java中的Thread.sleep有什么不同?
本文介绍了 Kotlin 中的 `delay` 函数与 Java 中 `Thread.sleep` 方法的区别。两者均可暂停代码执行,但 `delay` 适用于协程,非阻塞且高效;`Thread.sleep` 则阻塞当前线程。理解这些差异有助于提高程序效率与可读性。
39 1
|
1月前
|
Java Android开发 开发者
Kotlin 循环与函数详解:高效编程指南
高效编程实践 • 避免不必要的循环 - 尽量使用集合操作如 map、filter 来减少显式的循环。 • 使用尾递归优化 - 对于需要大量递归的情况,考虑使用尾递归以优化性能。 • 内联函数 - 对于传递 Lambda 表达式的函数,使用 inline 关键字可以减少运行时开销。 通过上述指南,您应该能够更好地理解 Kotlin 中的循环和函数,并能够编写更加高效和简洁的代码。Kotlin 的设计哲学鼓励开发者编写易于理解和维护的代码,而掌握循环和函数是实现这一目标的关键步骤。 如果您想了解更多关于 Kotlin 的循环和函数的信息,以下是一些官方文档和资源,它们可以提供额外的参考
31 1
|
1月前
|
Java Kotlin
Kotlin 循环与函数详解:高效编程指南
Kotlin中的循环结构让你能轻松遍历数组或范围内的元素。使用`for`循环结合`in`操作符,可以简洁地访问数组中的每个项,如字符串数组或整数数组。对于范围,可以用`..`来定义一系列连续的值并进行迭代。此外,Kotlin支持通过`break`和`continue`控制循环流程。函数则允许封装可复用的代码块,你可以定义接受参数并返回值的函数,利用简写语法使代码更加紧凑。例如,`myFunction(x: Int, y: Int) = x + y`简洁地定义了一个计算两数之和的函数。
38 1
|
2月前
|
Swift iOS开发 Kotlin
苹果iOS新手开发之Swift中实现类似Kotlin的作用域函数
Swift可通过扩展实现类似Kotlin作用域函数效果。如自定义`let`, `run`, `with`, `apply`, `also`,增强代码可读性和简洁性。虽无直接内置支持,但利用Swift特性可达成相似功能。
48 7
|
4天前
|
Android开发 开发者 Kotlin
告别AsyncTask:一招教你用Kotlin协程重构Android应用,流畅度飙升的秘密武器
【9月更文挑战第13天】随着Android应用复杂度的增加,有效管理异步任务成为关键。Kotlin协程提供了一种优雅的并发操作处理方式,使异步编程更简单直观。本文通过具体示例介绍如何使用Kotlin协程优化Android应用性能,包括网络数据加载和UI更新。首先需在`build.gradle`中添加coroutines依赖。接着,通过定义挂起函数执行网络请求,并在`ViewModel`中使用`viewModelScope`启动协程,结合`Dispatchers.Main`更新UI,避免内存泄漏。使用协程不仅简化代码,还提升了程序健壮性。
13 1
|
1月前
|
调度 Android开发 开发者
【颠覆传统!】Kotlin协程魔法:解锁Android应用极速体验,带你领略多线程优化的无限魅力!
【8月更文挑战第12天】多线程对现代Android应用至关重要,能显著提升性能与体验。本文探讨Kotlin中的高效多线程实践。首先,理解主线程(UI线程)的角色,避免阻塞它。Kotlin协程作为轻量级线程,简化异步编程。示例展示了如何使用`kotlinx.coroutines`库创建协程,执行后台任务而不影响UI。此外,通过协程与Retrofit结合,实现了网络数据的异步加载,并安全地更新UI。协程不仅提高代码可读性,还能确保程序高效运行,不阻塞主线程,是构建高性能Android应用的关键。
37 4
|
2月前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
95 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
|
2月前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin中常见作用域函数
**Kotlin作用域函数概览**: `let`, `run`, `with`, `apply`, `also`. `let`安全调用并返回结果; `run`在上下文中执行代码并返回结果; `with`执行代码块,返回结果; `apply`配置对象后返回自身; `also`附加操作后返回自身
38 8
|
2月前
|
安全 Java Android开发
探索Android应用开发中的Kotlin语言
【7月更文挑战第19天】在移动应用开发的浩瀚宇宙中,Kotlin这颗新星以其简洁、安全与现代化的特性,正迅速在Android开发者之间获得青睐。从基本的语法结构到高级的编程技巧,本文将引导读者穿梭于Kotlin的世界,揭示其如何优化Android应用的开发流程并提升代码的可读性与维护性。我们将一起探究Kotlin的核心概念,包括它的数据类型、类和接口、可见性修饰符以及高阶函数等特性,并了解这些特性是如何在实际项目中得以应用的。无论你是刚入门的新手还是寻求进阶的开发者,这篇文章都将为你提供有价值的见解和实践指导。
|
2月前
|
SQL 安全 Java
Android经典面试题之Kotlin中object关键字实现的是什么类型的单例模式?原理是什么?怎么实现双重检验锁单例模式?
Kotlin 单例模式概览 在 Kotlin 中,`object` 关键字轻松实现单例,提供线程安全的“饿汉式”单例。例如: 要延迟初始化,可使用 `companion object` 和 `lazy` 委托: 对于参数化的线程安全单例,结合 `@Volatile` 和 `synchronized`
40 6