Kotlin 學(xué)習(xí)筆記(十三)高階函數(shù)

image
image

上一篇 - kotlin中 集合序列使用、操作符匯總

前言
本篇博客為本人學(xué)習(xí)Kotlin 中所遇到的問題,如果哪里寫的不對(duì),希望歐大佬幫忙指出,多謝。

高階函數(shù)簡(jiǎn)單介紹

??一句話概括高階函數(shù):在Kotlin中,高階函數(shù)即指:將函數(shù)用作一個(gè)函數(shù)的參數(shù)或者返回值的函數(shù)。

參數(shù)為高階函數(shù)

??先看一段String.kt 文件中的擴(kuò)展函數(shù)

/**
 * Returns the sum of all values produced by [selector] function applied to each character in the char sequence.
 */
// inline 前邊寫過是內(nèi)聯(lián)函數(shù) (一般都和 lambda結(jié)合使用 ,優(yōu)化函數(shù)調(diào)用詳情參考 學(xué)習(xí)筆記十)
// CharSequence. 則是擴(kuò)展函數(shù)
public inline fun CharSequence.sumByDouble(selector: (Char) -> Double): Double {
    // selector參數(shù) 也是一個(gè)fun ,傳入char對(duì)象 輸入 Double對(duì)象
    var sum: Double = 0.0
    for (element in this) {
        sum += selector(element)
    }
    return sum
}

??經(jīng)過注釋講解,大概猜到該函數(shù)是將傳入的字符串 遍歷轉(zhuǎn)換為 Double,并增加,最后返回Double 類型的總和。

返回值為高階函數(shù)

這里使用官網(wǎng)上的一個(gè)例子

// 參數(shù)一接收 Lock類型 、接受一個(gè)無參且返回類型為T的函數(shù)作為參數(shù)二
fun <T> lock(lock: Lock, body:()->T):T{
        lock.lock()
        try {
            // 函數(shù)返回值
            return body()
        }
        finally {
            lock.unlock()
        }
    }

我們通過一個(gè)偽代碼,更直接的看一下

fun toBeSynchronized() = sharedResource.operation()
val result = lock(lock, ::toBeSynchronized)    

//簡(jiǎn)寫
val result = lock(lock, {sharedResource.operation()} )

常用高階函數(shù)

都集中在 Standard.kt

TODO

源碼 :

/**
 * Always throws [NotImplementedError] stating that operation is not implemented.
 *
 * @param reason a string explaining why the implementation is missing.
 */
@kotlin.internal.InlineOnly
public inline fun TODO(reason: String): Nothing = throw NotImplementedError("An operation is not implemented: $reason")
// inline 添加上有利于調(diào)用的時(shí)候 不需要再跳轉(zhuǎn)到改函數(shù)中使用,減少運(yùn)行消耗時(shí)間

run函數(shù)

@kotlin.internal.InlineOnly
public inline fun <R> run(block: () -> R): R {
    //契約 (run also with apply also 標(biāo)準(zhǔn)函數(shù)庫都用到了契約)
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

??該契約表示告訴編譯器:調(diào)用run函數(shù)后產(chǎn)生效果是指定block lamba表達(dá)式參數(shù)在適當(dāng)?shù)奈恢帽徽{(diào)用。適當(dāng)位置就是block lambda表達(dá)式只能在自己函數(shù)(這里就是指外層apply函數(shù))被調(diào)用期間被調(diào)用,當(dāng)run函數(shù)被調(diào)用結(jié)束后,block表達(dá)式不能被執(zhí)行,并且指定了InvocationKind.EXACTLY_ONCE表示block lambda表達(dá)式只能被調(diào)用一次,此外這個(gè)外層函數(shù)還必須是個(gè)inline內(nèi)聯(lián)函數(shù)。(契約更像告訴編譯器自身上下文關(guān)系)
??當(dāng)我們需要執(zhí)行一個(gè)代碼塊的時(shí)候就可以用到這個(gè)函數(shù),并且這個(gè)代碼塊是獨(dú)立的。即我可以在run()函數(shù)中寫一些和項(xiàng)目無關(guān)的代碼,因?yàn)樗粫?huì)影響項(xiàng)目的正常運(yùn)行。

舉例:

private fun printString(index: Int) {
        val str = "kotlin"
        var l = kotlin.run {
            when (index) {
                1 -> {
                    "java"
                }
                2 -> {
                    "php"
                }
                else -> {
                    "lua"
                }
            }
        }.length
        print(str + l)
    }

如上述代碼,在print代碼執(zhí)行的時(shí)候,會(huì)等待 run方法塊的執(zhí)行結(jié)果返回。

T.run()

大眼看過去 感覺 T.run() 和 run() 差別不大,但是在使用的時(shí)候會(huì)有不小的區(qū)別

源碼:

@kotlin.internal.InlineOnly
public inline fun <T, R> T.run(block: T.() -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block()
}

我們通過一段代碼模擬一下使用環(huán)境

private var str = "java"

    fun printStr(){
        str.run {
            print("${this.length}")
            print("${this.last()}")
            print("${first()}")
        }
    }

上述代碼中 T.run方法塊中可以使用this關(guān)鍵字 來代替本身,也可以省略,更適合多行代碼使用同一對(duì)象的情況,如果通過源碼查看,可以發(fā)現(xiàn) block()就是個(gè)T類型的擴(kuò)展函數(shù)。

關(guān)于更多的高階函數(shù) also with apply 等請(qǐng)移步 Kotlin中的庫函數(shù): run、with、let、also和apply

下一篇 - Kotlin 學(xué)習(xí)筆記(十四)淺讀協(xié)程

最后編輯于
?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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