
前言
本篇博客為本人學(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