美文网首页程序员
Kotlin 作用域函数

Kotlin 作用域函数

作者: 农民工Alan | 来源:发表于2020-08-19 16:42 被阅读0次

1、作用域函数区别表

fun main() {
    val numbers = mutableListOf("one", "two", "three")
    val countEndsWithE = numbers.run { 
        add("four")
        add("five")
        count { it.endsWith("e") }
    }
    println("There are $countEndsWithE elements that end with e.")
}

学习方法:取上述demo,将let、run、with、apply、also相互替换更改试试
Kotlin标准库包含几个函数,它们的唯一目的是在对象的上下文中执行代码块。当对一个对象调用这样的函数并提供一个lambda表达式时,它会形成一个临时作用域。在此作用域中,可以访问该对象而无需其名称。这些函数称为作用域函数。共有以下五种:let、run、with、apply以及also。

为了帮助你选择合适的作用域函数,我们提供了它们之间的主要区别表。

函数 对象引用 返回值 是否是扩展函数
let it Lambda表达式结果
run this Lambda表达式结果
run - Lambda表达式结果 不是:调用无需上下文对象
with this Lambda表达式结果 不是:把上下文对象当做参数
apply this 上下文对象
also it 上下文对象

以下是根据预期目的选择作用域函数的简短指南:
— 对一个非空(non-null)对象执行lambda表达式:let
— 将表达式作为变量引入为局部作用域中:let
— 对象配置:apply
— 对象配置并且计算结果:run
— 在需要表达式的地方运行语句:非扩展的run
— 附加效果:also
— 一个对象的一组函数调用:with

不同函数的使用场景存在重叠,你可以根据项目或团队中使用的特定约定选择函数。

尽管作用域函数是使代码更简洁的一种方法,但请避免过度使用它们:这会降低代码的可读性并可能导致错误。避免嵌套作用域函数,同时链式调用它们时要小心:此时很容易对当前上下文对象及this或it的值感到困惑。

2、源码

由于作用域函数本质上都非常相似,因此了解它们之间的区别很重要。每个作用域函数之间有两个主要区别:
— 引用上下文对象的方式
— 返回值
此外,当将上下文对象作为参数传递时,可以为上下文对象指定在作用域内的自定义名称。

fun getRandomInt(): Int {
    return Random.nextInt(100).also { value ->
        writeToLog("getRandomInt() generated value $value")
    }
}

使用 let 的另一种情况是引入作用域受限的局部变量以提高代码的可读性。如需为上下文对象定义一个新变量,可提供其名称作为 lambda 表达式参数来替默认的 it。

返回值
根据返回结果,作用域函数可以分为以下两类:
— apply及also返回上下文对象
— let、run及with返回lambda表达式结果
这两个选项使你可以根据在代码中的后续操作来选择适当的函数

/**
 * Calls the specified function [block] and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#run).
 */
@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

/**
 * Calls the specified function [block] with `this` value as its receiver and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#run).
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

/**
 * Calls the specified function [block] with the given [receiver] as its receiver and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#with).
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return receiver.block()
}

/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#apply).
 */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block()
    return this
}

/**
 * Calls the specified function [block] with `this` value as its argument and returns `this` value.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#also).
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.also(block: (T) -> Unit): T {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    block(this)
    return this
}

/**
 * Calls the specified function [block] with `this` value as its argument and returns its result.
 *
 * For detailed usage information see the documentation for [scope functions](https://kotlinlang.org/docs/reference/scope-functions.html#let).
 */
@kotlin.internal.InlineOnly
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}

/**
 * Returns `this` value if it satisfies the given [predicate] or `null`, if it doesn't.
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (predicate(this)) this else null
}

/**
 * Returns `this` value if it _does not_ satisfy the given [predicate] or `null`, if it does.
 */
@kotlin.internal.InlineOnly
@SinceKotlin("1.1")
public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
    contract {
        callsInPlace(predicate, InvocationKind.EXACTLY_ONCE)
    }
    return if (!predicate(this)) this else null
}

/**
 * Executes the given function [action] specified number of [times].
 *
 * A zero-based index of current iteration is passed as a parameter to [action].
 *
 * @sample samples.misc.ControlFlow.repeat
 */
@kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) -> Unit) {
    contract { callsInPlace(action) }

    for (index in 0 until times) {
        action(index)
    }
}

相关文章

  • 详解Kotlin中的作用域函数

    Kotlin作用域函数 作用域函数,Kotlin在语法层面支持拓展函数,作用域函数,作用域函数是指对数据做一些变换...

  • kotlin中Scope函数

    Scope函数翻译过来就叫作用域函数吧,Kotlin中的作用域函数包含let, run with, apply, ...

  • Kotlin修炼指南

    Kotlin修炼指南 作用域函数 作用域函数是Kotlin中的一个非常有用的函数,它主要分为两种,一种是拓展函数式...

  • Kotlin 常用作用域函数,区别和使用

    1. 有关作用域函数: Kotlin 中有很多作用域函数, 但是常见的使用场景是不同的。 常见的五种作用域函数 l...

  • [Kotlin Tutorials 10] Scope Func

    Scope Functions: Kotlin中的作用域函数 Kotlin标准库提供了5个scope functi...

  • Kotlin 作用域函数

    1、作用域函数区别表 学习方法:取上述demo,将let、run、with、apply、also相互替换更改试试K...

  • kotlin 作用域函数

    kotlin 作用域函数 作用:它们的唯一目的是在对象的上下文中执行代码块。当对一个对象调用这样的函数并提供一个 ...

  • Kotlin作用域函数

    kotlin中经常出现run、with、let、also、apply,开始时候容易迷糊,有什么用有什么区别? 一:...

  • Kotlin:作用域函数

    前言 最近使用kotlin语言开发了新的项目,kotlin的一些特性和大量的语法糖相当好用,相比于java,开发效...

  • Kotlin 作用域函数

    上面是常用的五个作用域函数 run let with apply also从定义上我们看出apply 和 also...

网友评论

    本文标题:Kotlin 作用域函数

    本文链接:https://www.haomeiwen.com/subject/paorjktx.html