了解 Kotlin 的必要性

Understanding the need for Kotlin let

我正在尝试理解为什么需要 let。在下面的示例中,我有一个 class 测试函数 giveMeFive:

public class Test() {
    fun giveMeFive(): Int {
        return 5
    }
}

给定以下代码:

var test: Test? = Test()

var x: Int? = test?.giveMeFive()

test = null

x = test?.giveMeFive()
x = test?.let {it.giveMeFive()}

x 设置为 5,然后在 test 设置为 null 后,为 x 调用以下任一语句 return null。鉴于在空引用上调用方法会跳过调用并将 x 设置为空,为什么我还需要使用 let?在某些情况下只是?行不通,需要 let 吗?

此外,如果被调用的函数没有 return 任何东西,那么 ?.将跳过通话,我不需要?。让那里。

如果要链接未在链接类型上定义的函数调用,则需要使用 let

假设您的函数定义是这样的:

// Not defined inside the Test class
fun giveMeFive(t: Test) {
    return 5
}

现在,如果您有一个可为 null 的 Test 并想在链中调用此函数,则必须使用 let:

val x = test?.let { giveMeFive(it) }

let()

fun <T, R> T.let(f: (T) -> R): R = f(this)

let() 是一个作用域函数:只要您想为代码的特定范围定义变量但不能超出范围,就可以使用它。让你的代码很好地独立是非常有用的,这样你就没有变量“泄漏”:可以访问它们应该在的地方。

DbConnection.getConnection().let { connection ->
}

// 连接在这里不再可见

let() 也可以用作针对 null 进行测试的替代方法:

val map : Map<String, Config> = ...
val config = map[key]
// config is a "Config?"
config?.let {
// This whole block will not be executed if "config" is null.
// Additionally, "it" has now been cast to a "Config" (no 
question mark)
}

Kotlin中的.let{}扩展函数:

  1. 对象引用作为调用.let{}的参数。

  2. Returnslet{} 函数返回的任何非原始数据类型的值。默认情况下,它 returns undefined 的值为 kotlin.Any class.

包kotlin中的声明:

public inline fun <T, R> T.let(block: (T) -> R): R {
    return block(this)
}

简单实用演示看看.let{}扩展函数在Kotlin中是如何工作的

示例代码1:-

val builder = StringBuilder("Hello ")
println("Print 0: $builder")

val returnVal = builder.let { arg ->
    arg.append("World")
    println("Print 1: $arg")

    "Done" // Returnning some string
}
println("Print 2: $builder")
println("Print 3: $returnVal")

示例代码 1 输出:-

Print 0: Hello 
Print 1: Hello World
Print 2: Hello World
Print 3: Done

In Sample Code 1:

  1. We created the final object of type StringBuilder with initialization value "Hello ".

  2. In builder.let{}, the builder object reference will be passed to arg.

  3. Here, the output Print 2: Hello World and Print 3: Hello World means that the builder and arg, both are pointing to the same StringBuilder object-reference. That's why they both print the same String value.

  4. In the last line of .let{} function block, we are returning "Done" String value which will be assigned to returnVal.

*Hence, we get Print 3: Done output from returnVal.

示例代码 2:-

val builder = StringBuilder("Hello ")
println("Print 0: $builder")
val returnVal = builder.let { arg ->
    arg.append("World")
    println("Print 1: $arg")
    arg.length
    }

println("Print 2: $builder")
println("Print 3: $returnVal") // Now return val is int = length of string.

示例代码 2 输出:-

Print 0: Hello 
Print 1: Hello World
Print 2: Hello World
Print 3: 11

In Sample Code 2:

What's difference:

In the last line of .let{} function block, we are returning the Int value equals to the length of StringBuilder object arg whose value at this line of code is "Hello World". So length = 11 of type Int will be assigned to returnVal.

*Hence, we get Print 3: 11 as output from returnVal.

也试试这些:-

  • .运行() {}
  • .apply() {}
  • with(obj) {}
  • .also() {}

编码愉快...

fun T.let(f: (T) -> R): R = f(this)

.let 块在多线程中不等于

验证值 x? =空

if(x == null) {
}

x?.let{
}

.let 块是线程安全的