Kotlin-作用域函數

一:概念

Kotlin 標準庫包含幾個函數,它們的唯一目的是在對象的上下文中執行代碼塊。當對一個對象調用這樣的函數並提供一個 lambda 表達式時,它會形成一個臨時作用域。在此作用域中,可以訪問該對象而無需其名稱。這些函數稱爲作用域函數。共有以下五種:letrunwithapply 以及 also

這些函數基本上做了同樣的事情:在一個對象上執行一個代碼塊。不同的是這個對象在塊中如何使用,以及整個表達式的結果是什麼。

先來看下如果不用作用域函數,我們平常是怎麼在進行處理代碼的。

   val alice = PersonMen("Alice", 20, "Amsterdam")
   alice.age=16
   alice.gj="Ydl"

通過作用域函數let看下是怎麼調用的:

  PersonMen("Alice", 20, "Amsterdam").let {
       it.age=30
       it.gj="London"
   }

可見使用了let函數,形成一個臨時的作用域。在此作用域中,可以訪問該對象而無需其名稱。

 

二:5個作用域函數的區別和相處

        以下的表格是對五個作用域函數的對比

作用域函數 上下文對象 返回結果類型 是否能單獨使用
let it(可自定義) lambda表達式的最後一行是返回值
also it(可自定義) T的類型(上下文對象)
run this(可隱式地訪問對象) lambda表達式的最後一行是返回值
apply this(可隱式地訪問對象) T的類型(上下文對象)
with this(可隱式地訪問對象) lambda表達式的最後一行是返回值

1:上下文對象

     var str: String= "Hello"

           str.let {
                println("let() called on $it")
            }

            str.also {
                println("also() called on $it")
            }

            str.run {
                println("run() called on $this")
            }

            str.apply {
                println("apply() called on $this")
            }

            with(str) {
                println("with() called on $this")
            }

輸出結果

let()   called on Hello
also()  called on Hello
run()   called on Hello
apply() called on Hello
with()  called on Hello
  • this可隱式地訪問對象,it不能
     str.let {
        it.length
      }

     str.run {
        this.length
        length
     }

從以上代碼可知,this省略也可以直接調用length,但是如果it省略直接寫 length ,代碼是會報錯

  • it作爲上下文可進行自定義這個上下文的名字
 str.let {value->
     value.length
 }

代碼中定義value爲上下文,但是this則不可以

2:返回結果類型

 var list: MutableList<String> = mutableListOf<String>()
  list.add("b")
  var letResult = list.let {
    it.add("a")
   }

  println("let() called on $letResult")
  println("let() called on $list")

結果:

let() called on true
let() called on [b, a]

可以看出let函數返回結果是:lambda表達式的最後一行的值

換成also函數:

  var list: MutableList<String> = mutableListOf<String>()
   list.add("b")
   var letResult = list.also {
   it.add("a")
   }

    println("also() called on $letResult")
    println("also() called on $list")

輸出結果:

also() called on [b, a]
also() called on [b, a]

可以看出also函數返回結果是:T的類型(上下文對象)

3.是否能單獨使用

這個在我的理解是是否一定要跟在"."的後面,這樣就限制了函數的使用位置,五種函數中不同的是with函數,with 可以理解爲“對於這個對象,執行以下操作。

 with(str) {
    println("with() called on $this")
 }

三:函數選擇

以下是根據預期目的選擇作用域函數的簡短指南:

  • 對一個非空(non-null)對象執行 lambda 表達式:let
  • 將表達式作爲變量引入爲局部作用域中:let
  • 對象配置:apply
  • 對象配置並且計算結果:run
  • 在需要表達式的地方運行語句:非擴展的 run
  • 附加效果:also
  • 一個對象的一組函數調用:with

不同函數的使用場景存在重疊,你可以根據項目或團隊中使用的特定約定選擇函數。

儘管作用域函數是使代碼更簡潔的一種方法,但請避免過度使用它們:這會降低代碼的可讀性並可能導致錯誤。避免嵌套作用域函數,同時鏈式調用它們時要小心:此時很容易對當前上下文對象及 this 或 it 的值感到困惑。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章