前言:被Elon Musk圈粉後,覺得他一定是我一輩子的偶像,他正做著一些那些夢寐以求,人類最浪漫最偉大的事情.
1.接收者的函式字面值
首先更正下我在 Kotlin 進階教程(一)文末分析apply原始碼的一個錯誤:
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }
複製程式碼
這個行內函數,是一個關於T的擴充套件函式,其入參block的寫法,看上去好像不太好理解;T.()是什麼玩意?最初我也把它理解成了T的擴充套件函式,這個理解是不對的,更正一下.雖然它的樣子很像擴充套件函式,但它並不是;它是一個帶有接收者的函式字面值. 接受者的函式字面值,怎麼理解呢; eg: 匿名函式語法允許直接指定函式字面值的接收者型別 所以可以如下定義一個匿名函式sum
val sum = fun Int.(another: Int): Int = this + another
複製程式碼
this代表呼叫者本身,那麼,我就可以這樣呼叫sum; eg:
val sum = 2.sum(3).sum(4)
println("$sum")
複製程式碼
輸出9; 顯而易見,我們可以讓呼叫者也成為入參的一部分,this表示; 所以apply函式可以輕鬆實現鏈式呼叫;
2.中綴函式
觀察如下程式碼
val map = mapOf<Int, String>(1 to "one", 2 to "two")
複製程式碼
可以看到1 to "one" 很方便對映了key-value 點進去看一下原始碼
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
複製程式碼
可以看到這個to函式是一個A的擴充套件函式,入參是B,所以我猜想 to 函式還可以這樣呼叫 1.to("one")
;
並且有infix修飾,infix即中綴函式的修飾符;
很顯然1.to("one"),
和1 to one
比較,後者更加簡潔優雅;
對於中綴函式,它只能有一個引數,切有infix修飾;
瞭解了中綴函式,那麼我們可以利用它發揮你的想象力,創造一些十分優雅的API .比如我們計算某個天數前的時間戳可以這麼寫:
val yesterday = 1 days ago
val theDayBeforeYesterday= 2 days ago
複製程式碼
程式碼看上就想在寫英文語句一樣;
object ago
infix fun Int.days(ago: ago):Long {
....//計算時間
return time
}
複製程式碼
3.行內函數
行內函數用inline修飾 在使用高階函式時會帶來一些執行時的效率損失:每一個函式都是一個物件,並且會得到一個閉包; 在(一)中我提過inline函式編譯器會將函式編譯成執行的程式碼塊,從而避免了函式頻繁的壓棧和出棧. 我們可以看到Kotlin的原始碼中,尤其是標準庫,大量使用了行內函數,行內函數會是效能有所提升; 所以在我們開發中,一些工具性函式,推薦liline函式;
lambda表示式中禁止裸用return進行函式返回,但是如果lambda 表示式傳給的函式是內聯的,該 return也可以內聯,所以它是允許的:
fun foo() {
lambda { _: Int, _: Int ->
println("內部已返回")
return //方法內聯,所以這裡是OK的
println("內部未返回")
}
println("lambda區域性返回,後續程式碼執行")
}
inline fun lambda( o: (x: Int, y: Int) -> Unit) {
o.invoke(3, 4)
}
複製程式碼
執行foo(),輸出:內部已返回; 可以看到這裡的return非區域性返回
但是如果傳入的lambda是內聯的,但是又不允許其非區域性控制流,那麼需要用crossinline修飾 eg:
fun foo() {
lambda { _: Int, _: Int ->
println("內部已返回")
// return //方法內聯,但是crossinlie修飾,所以這裡是不允許的,
return@lambda //標籤是允許的
println("內部未返回")
}
println("lambda區域性返回,後續程式碼執行")
}
inline fun lambda( crossinline o: (x: Int, y: Int) -> Unit) {
o.invoke(3, 4)
}
複製程式碼
執行foo(),輸出:
內部已返回
lambda區域性返回,後續程式碼執行
結尾
有理解錯誤的請指正!!! 重要的事情說三遍: kotlin很好用!
kotlin很好用!
kotlin很好用!