1. 程式人生 > >Kotlin之let,apply,with,run函數區別(轉)

Kotlin之let,apply,with,run函數區別(轉)

boolean () log 純粹 detail str2 let pre 並不是

轉自:https://blog.csdn.net/guijiaoba/article/details/54615036

Kotlin之let,apply,with,run函數區別


重新整理

重新整理了各種函數的區別,請移步到這裏。


以下作廢


很長一段時間內都一直使用Kotlin這門語言,也只是純粹使用簡單語法,最近有時候寫的代碼,編輯器自動提示使用let等函數,然後就專門花點時間研究了下。

let

首先let()的定義是這樣的,默認當前這個對象作為閉包的it參數,返回值是函數裏面最後一行,或者指定return

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

簡單示例:

fun testLet(): Int {
    // fun <T, R> T.let(f: (T) -> R): R { f(this)}
    "testLet".let {
        println(it)
        println(it)
        println(it)
        return 1
    }
}
//運行結果
//testLet
//testLet
//testLet
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

可以看看最後生成的class文件,代碼已經經過格式化了,編譯器只是在我們原先的變量後面添加了let裏面的內容。

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

來個復雜一定的例子

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
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

編譯過後的class文件

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

apply

apply函數是這樣的,調用某對象的apply函數,在函數範圍內,可以任意調用該對象的任意方法,並返回該對象

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

代碼示例

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) }
}

// 運行結果
// this = [testApply, testApply, testApply]
// [testApply, testApply, testApply]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

編譯過後的class文件

  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);
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

with

with函數是一個單獨的函數,並不是Kotlin中的extension,所以調用方式有點不一樣,返回是最後一行,然後可以直接調用對象的方法,感覺像是let和apply的結合。

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

代碼示例:

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) }
}
// 運行結果
// this = [testWith, testWith, testWith]
// kotlin.Unit
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

class文件

 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);
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

run

run函數和apply函數很像,只不過run函數是使用最後一行的返回,apply返回當前自己的對象。

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

代碼示例

fun testRun() {
    // fun <T, R> T.run(f: T.() -> R): R = f()
    "testRun".run {
        println("this = " + this)
    }.let { println(it) }
}
// 運行結果
// this = testRun
// kotlin.Unit
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

class文件

  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);
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

總結

怎麽樣,是不是看暈了,沒關系,我們來總結下。

函數名定義參數返回值extension其他
let fun T.let(f: (T) -> R): R = f(this) it 閉包返回
apply fun T.apply(f: T.() -> Unit): T { f(); return this } 無,可以使用this this
with fun with(receiver: T, f: T.() -> R): R = receiver.f() 無,可以使用this 閉包返回 調用方式與其他不同
run fun T.run(f: T.() -> R): R = f() 無,可以使用this 閉包返回

Kotlin之let,apply,with,run函數區別(轉)