Differences between let, apply, with and run functions of Kotlin

Rearrange

Rearranged the differences of various functions, please move to here.

Void below

Kotlin has been used for a long time. It only uses simple syntax. Recently, the editor automatically prompts the use of let and other functions in the code written sometimes, and then takes some time to study it.

let

First, let() is defined as this. By default, the current object is used as the it parameter of the closure, and the return value is the last line in the function, or specify return

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

Simple example:

fun testLet(): Int {
    // fun <T, R> T.let(f: (T) -> R): R { f(this)}
    "testLet".let {
        println(it)
        println(it)
        println(it)
        return 1
    }
}
//Operation results
//testLet
//testLet
//testLet

You can take a look at the last generated class file. The code has been formatted, and the compiler just added the contents of let after our original variables.

public static final int testLet() {
    String str1 = "testLet";
    String it = (String)str1;
    int $i$a$1$let;
    System.out.println(it);
    System.out.println(it);
    System.out.println(it);
    return 1;
}

Let's take a complicated example

fun testLet(): Int {
    // fun <T, R> T.let(f: (T) -> R): R { f(this)}
    "testLet".let {
        if (Random().nextBoolean()) {
            println(it)
            return 1
        } else {
            println(it)
            return 2
        }
    }
}

Compiled class file

public static final int testLet() {
    String str1 = "testLet";
    String it = (String)str1;
    int $i$a$1$let;
    if (new Random().nextBoolean())
    {
        System.out.println(it);
        return 1;
    }
    System.out.println(it);
    return 2;
}

apply

The apply function is to call the apply function of an object. Within the scope of the function, you can call any method of the object and return the object

fun <T> T.apply(f: T.() -> Unit): T { f(); return this }

Code example

fun testApply() {
    // fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
    ArrayList<String>().apply {
        add("testApply")
        add("testApply")
        add("testApply")
        println("this = " + this)
    }.let { println(it) }
}

// Operation results
// this = [testApply, testApply, testApply]
// [testApply, testApply, testApply]

Compiled class file

  public static final void testApply()
  {
    ArrayList localArrayList1 = new ArrayList();
    ArrayList localArrayList2 = (ArrayList)localArrayList1;
    int $i$a$1$apply;
    ArrayList $receiver;
    $receiver.add("testApply");
    $receiver.add("testApply");
    $receiver.add("testApply");
    String str = "this = " + $receiver;
    System.out.println(str);
    localArrayList1 = localArrayList1;
    ArrayList it = (ArrayList)localArrayList1;
    int $i$a$2$let;
    System.out.println(it);
  }

with

The with function is a separate function, not the extension in Kotlin, so the calling method is a little different. The return is the last line, and then you can directly call the method of the object, which feels like a combination of let and apply.

fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()

Code example:

fun testWith() {
    // fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
    with(ArrayList<String>()) {
        add("testWith")
        add("testWith")
        add("testWith")
        println("this = " + this)
    }.let { println(it) }
}
// Operation results
// this = [testWith, testWith, testWith]
// kotlin.Unit

class file

 public static final void testWith()
  {
    Object localObject = new ArrayList();
    ArrayList localArrayList1 = (ArrayList)localObject;
    int $i$a$1$with;
    ArrayList $receiver;
    $receiver.add("testWith");
    $receiver.add("testWith");
    $receiver.add("testWith");
    String str = "this = " + $receiver;
    System.out.println(str);
    localObject = Unit.INSTANCE;
    Unit it = (Unit)localObject;
    int $i$a$2$let;
    System.out.println(it);
  }

run

The run function is very similar to the apply function, except that the run function uses the return of the last line, and apply returns its own current object.

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

Code example

fun testRun() {
    // fun <T, R> T.run(f: T.() -> R): R = f()
    "testRun".run {
        println("this = " + this)
    }.let { println(it) }
}
// Operation results
// this = testRun
// kotlin.Unit

class file

  public static final void testRun()
  {
    Object localObject = "testRun";
    String str1 = (String)localObject;
    int $i$a$1$run;
    String $receiver;
    String str2 = "this = " + $receiver;
    System.out.println(str2);
    localObject = Unit.INSTANCE;
    Unit it = (Unit)localObject;
    int $i$a$2$let;
    System.out.println(it);
  }

summary

How is it? Is it dizzy? It doesn't matter. Let's sum up.

Function namedefinitionparameterReturn valueextensionother
letfun <T, R> T.let(f: (T) -> R): R = f(this)itClosure returnyes 
applyfun <T> T.apply(f: T.() -> Unit): T { f(); return this }None, you can use thisthisyes 
withfun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()None, you can use thisClosure returnnoThe calling method is different from others
runfun <T, R> T.run(f: T.() -> R): R = f()None, you can use thisClosure returnyes 



Author: running water does not rot Xiaoxia
Link: https://www.jianshu.com/p/28ce69d58fea
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.

Keywords: kotlin

Added by tablex on Fri, 11 Feb 2022 06:05:26 +0200