[英]Confusing function type usage in Kotlin
我正在閱讀 kotlin 協程源代碼。
請參閱下面的代碼快照:
public operator fun <R, T> invoke(block: suspend R.() -> T, receiver: R, completion: Continuation<T>): Unit =
when (this) {
DEFAULT -> block.startCoroutineCancellable(receiver, completion)
ATOMIC -> block.startCoroutine(receiver, completion)
UNDISPATCHED -> block.startCoroutineUndispatched(receiver, completion)
LAZY -> Unit // will start lazily
}
在 CoroutineStart.kt 中
和
internal fun <R, T> (suspend (R) -> T).startCoroutineCancellable(
receiver: R, completion: Continuation<T>,
onCancellation: ((cause: Throwable) -> Unit)? = null
) =
runSafely(completion) {
createCoroutineUnintercepted(receiver, completion).intercepted().resumeCancellableWith(Result.success(Unit), onCancellation)
}
在 Cancellable.kt 中
我的困惑是:
作為 function 類型為R.() -> T
的block
,它如何調用startCoroutineCancellable
類型為(R) -> T
的 function
這在語言規范的“ Function Types ”部分(強調我的)中進行了解釋。
具有接收
FTR
的 function 類型FTR(RT, A1, A2, ... An) -> R
[...]
從類型系統的角度來看,它相當於下面的 function 類型
FTR(RT, A1, A2, ... An) -> R ≡ FT(RT, A1, A2, ... An) -> R
即接收者被認為是其 function 類型的另一個參數。
[...] 例如,這兩種類型等同於 w.r.t。 類型系統
Int.(Int) -> String (Int, Int) -> String
因此R.() -> T
的實例完全可以用作(R) -> T
上擴展的接收者,反之亦然,因為類型系統將它們視為同一事物。
請注意,這兩種類型在重載決議的上下文中是不同的。 例如,如果你說someInt.bar()
,並且 scope 中有兩個bar
,一個類型為Int.() -> Unit
,另一個類型為(Int) -> Unit
,那么重載解析將知道這些是具有不同類型的函數並選擇前一個。
旁注: startCoroutineCancellable
和invoke
中使用的 function 類型在技術上暫停了 function 類型,但上面說的仍然適用。
R.() -> T
和(R) -> T
從調用者的角度來看是非常相似的 function 類型。 他們只收到R
並返回T
。 它們的主要區別在於身體的角度。 看這個例子:
val f1: Int.() -> String = { toString() }
val f2: (Int) -> String = f1
val f3: Int.() -> String = f2
如我們所見,我們可以在兩種類型之間自由轉換,甚至無需顯式強制轉換。
一種簡明扼要的表達方式是,使用接收者定義的 function 類型與將接收者作為第一個參數移入參數的簽名具有相同的簽名。 它們幾乎在任何地方都可以互換,除非使用 lambda 表達式來表示它們,以及調用它們時。 您可以調用帶有接收器的 function ,並將接收器轉換為第一個參數(反之亦然,在其第一個參數的實例上調用無接收器 function )。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.