Understanding the need for Kotlin let

巧了我就是萌 提交于 2020-12-12 11:37:26

问题


I'm trying to understand why let is needed. In the example below I have a class Test with a function giveMeFive:

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

Given the following code:

var test: Test? = Test()

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

test = null

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

x gets set to 5, then after test is set to null, calling either of the following statements return null for x. Given that calling a method on a null reference skips the call and sets x to null, why would I ever need to use let? Are some cases where just ?. won't work and let is required?

Further, if the function being called doesn't return anything, then ?. will skip the call and I don't need ?.let there either.


回答1:


let()

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

let() is a scoping function: use it whenever you want to define a variable for a specific scope of your code but not beyond. It’s extremely useful to keep your code nicely self-contained so that you don’t have variables “leaking out”: being accessible past the point where they should be.

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

// connection is no longer visible here

let() can also be used as an alternative to testing against 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)
}

A simple go to chart when to use when.




回答2:


You need to use let if you want to chain function calls that aren't defined on the type you are chaining from.

Let's say the definition of your function was this instead:

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

Now, if you have a nullable Test and want to call this function in a chain, you have to use let:

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



回答3:


The .let{} extension function in Kotlin:

  1. Takes the object reference as the parameter on which .let{} is called.

  2. Returns value of any non-primitive data-type which has been returned from with let{} function. By default, it returns undefined value of kotlin.Any class.

Declaration in package kotlin:

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

Simple practical demonstration to see how .let{} extension function works in Kotlin.

Sample Code 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")

Sample Code 1 Output:-

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.

Sample Code 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.

Sample Code 2 Output:-

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.

Also try these:-

  • .run() {}
  • .apply() {}
  • with(obj) {}
  • .also() {}

Happy Coding...



来源:https://stackoverflow.com/questions/54382675/understanding-the-need-for-kotlin-let

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!