此自定義函式呼叫在 null 時是一個 lambda 塊。我希望下面的函式定義強制執行相同的回傳型別。: T
他們是強制執行 be 塊回傳型別T的方法嗎?
inline fun <T> T?.whenNull(block: () -> T): T {
if (this == null) {
return block() //accepts any return type
} else {
return this
}
}
fun main() {
val x : Int? = null
println(x ?: 42)
println(x.whenNull { 42 })
println(x.whenNull { "why is kotlin not enforcing return of the same type?" })
}
uj5u.com熱心網友回復:
有趣的是,當將它傳遞給塊時,型別被保留并按預期作業。
inline fun <T> T?.whenNullAlt(block: (T?) -> T): T {
if (this == null) {
return block(this) // "this" is superfluous, but enforces same return type
} else {
return this
}
}
fun main() {
val x : Int? = null
println(x.whenNullAlt { 42 })
println(x.whenNullAlt { "does not compile" })
}
uj5u.com熱心網友回復:
T在第二個whenAll電話中被推斷為Any. 想象一下,所有出現的T都被替換Any,呼叫將是有效的,你不同意嗎?畢竟都是 的子型別Int。StringAny
inline fun Any?.whenNull(block: () -> Any): Any {
if (this == null) {
return block()
} else {
return this
}
}
fun main() {
println(x.whenNull { "why is kotlin not enforcing return of the same type?" })
}
基本上,Kotlin 編譯器在這里“太努力”以使您的代碼編譯,并為您的型別引數推斷出意外的型別。
如果函式的輸入型別之一(引數型別、接收器型別等)中未提及推斷的型別,則存在一個內部注釋@kotlin.internal.InputTypesOnly將阻止您的代碼編譯。
在這種情況下,輸入型別只是Int?,并且T被推斷為Any,所以這會使您的代碼無法按預期編譯。不幸的是,這個注釋是內部的,你不能使用它 :( KT-13198是讓它公開的票。
uj5u.com熱心網友回復:
正如其他答案指出的那樣,從 Kotlin 的角度來看,這在技術上是正確的,因為它可以推斷T并且Any可以編譯。
然而,雖然技術上是正確的,但這是 Kotlin 語言中的一個已知問題,總有一天會得到解決。注意到了,讓我們試著理解為什么你的答案的代碼有效,而你的問題卻沒有。
這樣做的原因是 lambda 總是最后推斷出來的:想象它是一個佇列,其中包含運算式的哪些部分需要推斷其型別,并且 lambda 中的任何內容始終位于佇列的末尾,無論 lambda 在哪里在運算式中。因此,在查看您的示例時,它會推斷出其他所有內容,決定this應該是的型別Int?,而不是轉到 lambda,查看String回傳型別并將它們合并為Any對自己感到非常自豪。
然而,在另一個例子中,lambda 被傳遞了一個關于它的引數的外部事實——已經Int從接收器推斷出(lambda 總是最后一個獲取資訊,還記得嗎?)。這樣lambda內部的推理就會失敗,因為引數和結果型別不一致。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/494519.html
