Kotlin标准函数run with let also apply的区别

简介: Kotlin标准函数run with let also apply的区别

Kotlin的Standard.kt中的一些函数很相像,很多时候我们不确定使用哪个。这篇文章我将教大家如何区分他们的不同,以及如何在正确的场景下使用正确的函数

1_9nUzj5iRxj_Hddni6ob28w.pngStandard.kt中有 run,T.run,with,T.apply,T.also,T.let几个函数,他们的共同的功能都是执行程序。但是他们之间还是有区别的。


一共有6个函数。我将根据返回值以及block函数的参数对它归类

1_pLNnrvgvmG6Mdi0Yw3mdPQ.png


T.apply和T.also是一对,它们的返回值为this,他们的区别在于apply block参数中传递的是this,also block参数中传递的是it


T.run和T.let是一对,它们的返回值是block执行的结果,它们的区别在于run block参数传递的是this,let block参数传递的是it


run和with是一对,run block参数中既不是this也不是it。with block参数是this


函数块



首先我们用run函数来演示下函数块

fun test() {
    var mood = "I am sad"
    run {
        val mood = "I am happy"
        println(mood) // I am happy
    }
    println(mood)  // I am sad
}

在函数块中我们可以重新声明mood变量


with和T.run对比

with(webview.settings) {
    javaScriptEnabled = true
    databaseEnabled = true
}
// similarly
webview.settings.run {
    javaScriptEnabled = true
    databaseEnabled = true
}

他们两实现的功能是一样的。如果webview.setting可能为null

// Yack!
with(webview.settings) {
      this?.javaScriptEnabled = true
      this?.databaseEnabled = true
   }
}
// Nice.
webview.settings?.run {
    javaScriptEnabled = true
    databaseEnabled = true
}

this vs it参数

stringVariable?.run {
      println("The length of this String is $length")
}
// Similarly.
stringVariable?.let {
      println("The length of this String is ${it.length}")
}

如果你检查T.run函数签名,你会发现T.run它只是作为扩展函数调用block: T.()。因此,在范围内,T可以称为this。在编程中,this大多数时候可以省略。因此,在上面的示例中,我们可以l e n g t h 在 p r i n t l n 语 句 中 使 用 , 而 不 是 length在println语句中使用,而不是length在println语句中使用,而不是{this.length}。我称之为发送此作为参数。


返回this vs 返回other

stringVariable?.let {
      println("The length of this String is ${it.length}")
}
// Exactly the same as below
stringVariable?.also {
      println("The length of this String is ${it.length}")
}

他们微妙的不同就是他们的返回值。T.let返回的是函数快的返回值Unit,而T.also返回T本身即this

val original = "abc"
// Evolve the value and send to the next chain
original.let {
    println("The original String is $it") // "abc"
    it.reversed() // evolve it as parameter to send to next let
}.let {
    println("The reverse String is $it") // "cba"
    it.length  // can be evolve to other type
}.let {
    println("The length of the String is $it") // 3
}
// Wrong
// Same value is sent in the chain (printed answer is wrong)
original.also {
    println("The original String is $it") // "abc"
    it.reversed() // even if we evolve it, it is useless
}.also {
    println("The reverse String is ${it}") // "abc"
    it.length  // even if we evolve it, it is useless
}.also {
    println("The length of the String is ${it}") // "abc"
}
// Corrected for also (i.e. manipulate as original string
// Same value is sent in the chain 
original.also {
    println("The original String is $it") // "abc"
}.also {
    println("The reverse String is ${it.reversed()}") // "cba"
}.also {
    println("The length of the String is ${it.length}") // 3
}

他们微妙的不同就是他们的返回值。T.let返回的是函数快的返回值Unit,而T.also返回T本身即this

val original = "abc"
// Evolve the value and send to the next chain
original.let {
    println("The original String is $it") // "abc"
    it.reversed() // evolve it as parameter to send to next let
}.let {
    println("The reverse String is $it") // "cba"
    it.length  // can be evolve to other type
}.let {
    println("The length of the String is $it") // 3
}
// Wrong
// Same value is sent in the chain (printed answer is wrong)
original.also {
    println("The original String is $it") // "abc"
    it.reversed() // even if we evolve it, it is useless
}.also {
    println("The reverse String is ${it}") // "abc"
    it.length  // even if we evolve it, it is useless
}.also {
    println("The length of the String is ${it}") // "abc"
}
// Corrected for also (i.e. manipulate as original string
// Same value is sent in the chain 
original.also {
    println("The original String is $it") // "abc"
}.also {
    println("The reverse String is ${it.reversed()}") // "cba"
}.also {
    println("The length of the String is ${it.length}") // 3
}

使用

// Normal approach
fun makeDir(path: String): File  {
    val result = File(path)
    result.mkdirs()
    return result
}
// Improved approach
fun makeDir(path: String) = path.let{ File(it) }.also{ it.mkdirs() }
// Normal approach
fun createInstance(args: Bundle) : MyFragment {
    val fragment = MyFragment()
    fragment.arguments = args
    return fragment
}
// Improved approach
fun createInstance(args: Bundle) 
              = MyFragment().apply { arguments = args }
// Normal approach
fun createIntent(intentData: String, intentAction: String): Intent {
    val intent = Intent()
    intent.action = intentAction
    intent.data=Uri.parse(intentData)
    return intent
}
// Improved approach, chaining
fun createIntent(intentData: String, intentAction: String) =
        Intent().apply { action = intentAction }
                .apply { data = Uri.parse(intentData) }



相关文章
|
1月前
|
Java Kotlin
[AIGC] Java 和 Kotlin 的区别
[AIGC] Java 和 Kotlin 的区别
21 0
|
8月前
|
API Kotlin
Kotlin中扩展函数、infix关键字、apply函数和DSL的详解
Kotlin中扩展函数、infix关键字、apply函数和DSL的详解
77 0
|
8月前
|
安全 Java Kotlin
Kotlin中空安全操作符,异常处理和自定义异常,以及先决条件函数详解
Kotlin中空安全操作符,异常处理和自定义异常,以及先决条件函数详解
86 0
|
6月前
|
存储 Java 编译器
Kotlin 学习笔记(四)—— 作用域函数、inline 关键字、反引号等 Kotlin 基本用法(下)
Kotlin 学习笔记(四)—— 作用域函数、inline 关键字、反引号等 Kotlin 基本用法(下)
33 0
|
6月前
|
Java Android开发 开发者
Kotlin 学习笔记(四)—— 作用域函数、inline 关键字、反引号等 Kotlin 基本用法(上)
Kotlin 学习笔记(四)—— 作用域函数、inline 关键字、反引号等 Kotlin 基本用法(上)
45 0
|
7月前
|
Java 开发者 Kotlin
Kotlin为什么会火起来,有什么特点,跟Java区别
Kotlin为什么会火起来,有什么特点,跟Java区别
80 0
|
8月前
|
安全 Java 编译器
Kotlin 学习笔记(一)—— 基本类型、函数、lambda、类与对象的写法
Kotlin 作为 Android 开发的首选语言,其基础语法和特性需要重点学习。本文概括总结了 Kotlin 的基本类型、关键字、函数、闭包、高阶函数、类与对象等核心知识点,并给出示例代码进行讲解。
152 0
Kotlin 学习笔记(一)—— 基本类型、函数、lambda、类与对象的写法
|
8月前
|
Java Kotlin
Kotlin中与Java互操作与可空性、类型映射、属性访问、@JvmOverloads、@JvmField、@JvmStatic、@Throws和函数类型操作详解
Kotlin中与Java互操作与可空性、类型映射、属性访问、@JvmOverloads、@JvmField、@JvmStatic、@Throws和函数类型操作详解
69 0
|
4天前
|
传感器 Android开发 开发者
构建高效Android应用:Kotlin的协程与Flow
【4月更文挑战第26天】随着移动应用开发的不断进步,开发者寻求更简洁高效的编码方式以应对复杂多变的业务需求。在众多技术方案中,Kotlin语言凭借其简洁性和强大的功能库逐渐成为Android开发的主流选择。特别是Kotlin的协程和Flow这两个特性,它们为处理异步任务和数据流提供了强大而灵活的工具。本文将深入探讨如何通过Kotlin协程和Flow来优化Android应用性能,实现更加流畅的用户体验,并展示在实际开发中的应用实例。
|
4天前
|
安全 数据处理 Android开发
构建高效Android应用:Kotlin协程的实践之路
【4月更文挑战第26天】 在面对现代Android开发时,性能优化和流畅的用户体验成为了开发者们追求的目标。Kotlin作为一种现代化的编程语言,通过其协程特性为Android应用带来了前所未有的并发处理能力。本文将深入探讨如何利用Kotlin协程提升Android应用的响应性和效率,同时保持代码的简洁性。我们将从协程的基础概念出发,逐步揭示如何在实际应用中运用这些强大的工具,以及它们如何改善应用架构和用户交互体验。