Koltin 高級(jí)篇 Lambda 簡潔之道

序言

最近一直在學(xué)習(xí) kotlin ,他給我的感覺是一門非常使用、簡潔的語言。Kotlin 支持函數(shù)式編程,而 Lambda 在 Kotlin 和 Kotlin DSL 中扮演著很重要的角色,是實(shí)現(xiàn)整潔代碼的必備語法糖。

Lambda 表達(dá)式的語法

一個(gè) lambda 把一小段行為進(jìn)行編碼,你能把它當(dāng)作值到處傳遞。它可以被獨(dú)立地聲明并存儲(chǔ)到一個(gè)變量中,但是更常見的還是直接聲明它井傳遞給函數(shù)(高階函數(shù))。

Kotlin in Action

Kotlin lambda 表達(dá)式始終用花括號(hào)包圍。注意實(shí)參并沒有用括號(hào)括起來
頭把實(shí)參列表和 lambda 的函數(shù)體隔開。

高階函數(shù)

就是這個(gè)函數(shù)可以接受另一個(gè)函數(shù)作為參數(shù)或者返回值
函數(shù)的形參總是 首先是括號(hào)里面是函數(shù)的入?yún)㈩愋?,然后箭頭后面跟的是函數(shù)返回值類型,沒有返回值要指定 Unit 如圖:

Kotlin in Action

下面是一個(gè) Android 中最常見的 view 的點(diǎn)擊事件在 分別用 java 和 kotlin 來實(shí)現(xiàn)

java 寫法
// java 1、首先要聲明接口 2、實(shí)例這個(gè)接口創(chuàng)建一個(gè)匿名內(nèi)部類
public interface OnClickListener {
    void onClick(View v);
}

button.setOnClickListener(new OnClickListener() {
  @Override
  public void onClick (View view) {
  /*點(diǎn)擊后執(zhí)行的動(dòng)作*/
  } 
)
kotlin lambda 寫法
// kotlin 高級(jí)函數(shù)聲明( 傳入 lambda )  view 類型參數(shù) 沒有返回值
fun setOnClickListener(listener: (View) -> Unit)
// kotlin 十分簡潔
button.setOnClickListener({ v: View -> print(v.name)})
kotlin lambda 如果這個(gè)函數(shù)的最后一個(gè)參數(shù)是一個(gè)函數(shù),我們可以把這個(gè)函數(shù)移動(dòng)到圓括號(hào)外面
button.setOnClickListener() { v: View -> print(v.name)}
kotlin lambda 如果這個(gè)函數(shù)只有一個(gè)參數(shù),我們可以省略這個(gè)圓括號(hào)
button.setOnClickListener{ v: View -> print(v.name)}
// 用 it 代替參數(shù)
button.setOnClickListener{ print(it.name)}
// 如果沒有用到 v 這個(gè)參數(shù)可以進(jìn)一步簡化
button.setOnClickListener { print("我就是簡潔...")}

我們將會(huì)在下一章中講解 lambda 表達(dá)式的經(jīng)典用途和集合一起工作,kotlin 是如何提供那么方便的集合庫

帶接收者的 lambda 和擴(kuò)展函數(shù)類型

首先我們還是先通過 來看為啥要用這個(gè)帶接收者的 lambda,他是怎么做到優(yōu)化的。
1、先定義一個(gè)個(gè)以普通 lambda 作為參數(shù)的 buildString 函數(shù)。

/**
* @param builderAction 定義函數(shù)類型的參數(shù)
*/
fun buildStringNormalLm(builderAction: (StringBuilder) -> Unit): String {
      val sb = java.lang.StringBuilder()
      // 傳遞一個(gè) StringBuilder 對(duì)象作為 lambda 的參數(shù)
      builderAction(sb)
      return sb.toString()
}
 //  調(diào)用普通的 lambda
val s = buildStringNormalLm {
      it.append("Hello,")
      it.append("World")
}
print(s)
// 打印結(jié)果 Hello,World

2、首先 it 這個(gè)對(duì)象執(zhí)行多次操作,我們不想反復(fù)把對(duì)象的名稱寫出來 就是未來這個(gè)目的....
3、要做到這點(diǎn),需要將 lambda 轉(zhuǎn)換成帶接收者的 lambda。

/**
* @param builderAction 定義帶接收者的函數(shù)類型的參數(shù)
*  StringBuilder. () -> Unit 擴(kuò)展函數(shù)聲明
*/
fun buildStringReceiverLm(builderAction: StringBuilder. () -> Unit): String {
      val sb = java.lang.StringBuilder()
      // 傳遞一個(gè) String Builder 實(shí)例作為 lambda 接收者
      sb.builderAction()
      return sb.toString()
}
// 調(diào)用帶接收者的 lambda
val s = buildStringReceiverLm {
       append("Hello,")
       append("World")
}
print(s)
// 打印結(jié)果 Hello,World

那為什么在 buildStringReceiverLm() 中可以直接調(diào)用 StringBuilder 實(shí)例那 ?

  • 主要是我們用 擴(kuò)展函數(shù)類型 取代 普通函數(shù)類型 來聲明參數(shù)的類型 。擴(kuò)展函數(shù)類型的聲明如下圖:
    Kotlin in Action

為什么要用擴(kuò)展函數(shù)類型?不需要顯式的修飾符就可以訪問一個(gè)外部類型的成
員讓我們想起了擴(kuò)展函數(shù),它可以讓我們?yōu)樵诖a其他地方定義的類定義自己的方法。擴(kuò)展函數(shù)和帶接收者的 lambda 都有一個(gè)接收者對(duì)象 ,當(dāng)函數(shù)被調(diào)用的時(shí)候需要提供這個(gè)對(duì)象,它在函數(shù)體內(nèi)是可用的。實(shí)際上一個(gè)個(gè)擴(kuò)展函數(shù)類型描述了可以被當(dāng)作擴(kuò)展函數(shù)來調(diào)用的代碼塊。

仔細(xì)看下面的截圖以及備注我想你一定能看明白

下一節(jié)我們會(huì)通過展示 Kotlin 標(biāo)準(zhǔn)庫中的 with 函數(shù)和 apply 函數(shù),來進(jìn)一步說明 帶接收者的 lambda 實(shí)際項(xiàng)目中用到的地方。

參考資料

Kotlin之美——DSL篇
《Kotlin 實(shí)戰(zhàn)》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容