日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

淺析Kotlin使用infix函數構建可讀語法流程講解_Android

作者:Mr?YiRan ? 更新時間: 2023-03-16 編程語言

我們在Kotlin中就多次使用A to B這樣的語法結構構建鍵值對,包括Kotlin自帶的mapOf()函數,這種語法結構的優點是可讀性強。那么這種功能是怎么實現的?to是不是Kotlin語言中的一個關鍵字?本章我們來對這個功能進行解密。

首先,to并不是Kotlin語言中的一個關鍵字,之所以我們能使用A to B這樣的語法結構,是因為Kotlin提供了一種高級語法糖特性:infix函數。infix函數只是把編程語言函數調用的語法規則調整了一些而已,比如A to B這樣的寫法,實際上等價于A.to(B)的寫法。

通過兩個具體的例子來學習一下infix函數的用法。

String類中有一個startsWith()函數,它可以用于判斷一個字符串是否以某個指定參數開頭的。比如說下面這段代碼的判斷結果一定會是true:

if("Hello Kotlin".startsWith("Hello")){
//處理具體的邏輯
}

startsWith()函數的用法雖然比較簡單,但是借助infix函數,我們可以使用一種更具可讀性的語法來表達這段代碼。新建一個infix.kt文件,然后編寫如下代碼:

infix fun String.beginWith(prefix:String)=startsWith(prefix)

首先,除去最前面的infix關鍵字,這是一個String類的擴展函數。我們給String類添加一個beginsWith()函數,它也是用于判斷一個字符串是否以某個指定參數開頭的,并且它的內部實現就是調用的String類的startsWith()函數。

但是加上了infix關鍵字后,beginsWith()函數就變成了infix函數,這樣除了傳統的函數調用方式之外,我們還可以用一種特殊的語法糖格式調用beginsWith()函數,如下所示:

if("Hello Kotlin" beginWith "Hello"){
//處理具體邏輯
}

從這個例子就可以看出,infix函數的語法規則并不復雜,上述代碼其實就是調用的"Hello Kotlin"這個字符串的beginWith()函數,并傳入了一個"Hello"字符串作為參數。但是infix函數允許我們將函數調用時的小數點、括號等計算機相關的語法去掉,從而使用一種更接近英語的語法來編寫程序,讓代碼看起來更加具有可讀性。

另外,infix函數由于其語法糖格式,有兩個比較嚴格的限制:

  • infix函數不能定義成頂層函數的,它必須是某個類的成員函數,可以使用擴展函數的方式將它定義到某個類當中。
  • infix函數必須接收且只能接收一個參數,至于參數類型是沒有限制的。

只有同時滿足這兩點,infix函數的語法糖才具備使用的條件。

接下來我們再看一個復雜一些的例子。比如這里有一個集合,如果你想要判斷集合中是否包含某個指定元素,一般可以這樣寫:

val list=listOf("Apple","Banana","Orange","Pear","Grape")
if(list.contains("Banana")){
//處理具體邏輯
}

但我們仍然可以借助infix函數讓這段代碼變得更加具有可讀性。在infix.kt文件中添加如下代碼:

infix fun <T> Collection<T>.has(element: T)=contains(element)

可以看到我們給Collection接口添加了一個擴展函數,這是因為Collection是Java以及Kotlin所有集合的總接口,因此給Collection添加一個has()函數,那么所有集合的子類都可以使用這個函數了。

另外,通過指定has函數的參數是泛型,所以has()函數可以接收任意具體類型的參數。而這個函數內部的實現邏輯就是調用了Collection接口中的contains()函數而已。也就是說,has()函數和contains()函數的功能是一模一樣的,只是它多了一個infix關鍵字,從而擁有了infix函數的語法糖功能。

現在我們就可以使用如下的語法來判斷集合中是否包括某個指定的元素:

val list=listOf("Apple","Banana","Orange","Pear","Grape")
if(list has "Banana"){
//處理具體邏輯
}

還有就是mapOf()函數中允許我們使用A to B這樣的語法來構建鍵值對,它的具體實現是怎樣的呢?我們通過查看源碼如下:

public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)

可以看到,這里使用定義泛型的方式將to()函數定義到了A類型下,并且接收一個B類型的參數。因此A和B可以是兩種不同類型的泛型,也就使得我們可以構建出字符串 to整型這樣的鍵值對。

再來看to()函數的具體實現,就是創建并返回了一個Pair對象,也就是說,A to B這樣的語法結構實際上得到的是一個包含A、B數據的Pair對象,而mapOf()函數實際上接收的正是一個Pair類型的可變參數列表。

我們也可以模仿to()函數的源碼來編寫一個自己的鍵值對構建函數。在infix.kt文件中添加如下代碼:

infix fun <A,B> A.with(that:B):Pair<A,B> =Pair(this,that) 

這里只是將to()函數改名成了with()函數,其他實現邏輯是相同的。而我們的項目中就可以使用with()函數來構建鍵值對了,還可以將鍵值對傳入maoOf()方法中:

val map=mapOf("Apple" with 1,"Banana" with 2,"Orange" with 3,"Pear" with 4,"Grape" with 5)

這樣通過靈活的使用infix函數,我們可以讓語法變得更具可讀性。

原文鏈接:https://blog.csdn.net/ChenYiRan123456/article/details/128395107

欄目分類
最近更新