為什么該程式在運行時因 ClassCastException 而失敗時會列印 kotlin.Unit?
class Animal<T> {
}
fun <T> Animal<T>.extension(block: ()-> T){
print(block())
}
fun main(){
//(4 as Unit) //Runtime ClassCastException, OK
//Animal<String>().extension { 2 2 } //Compilation error, ok
Animal<Unit>().extension { 2 2 } // Why no ClassCastException but prints kotlin.Unit?
}
如果這不是錯誤,是否可以強制執行約束?
uj5u.com熱心網友回復:
在解釋 lambda 運算式時,Kotlin 將回傳 Unit 的函式視為特殊情況。如果它期望 lambda 回傳 Unit,它將隱式回傳 Unit,而不管 lambda 的最后一行的計算結果是什么。否則,lambdas 將非常頻繁地在最后有一個無用的行來回傳Unit。因此,由于它解釋 lambda 的方式,這里沒有發生強制轉換。在 lambda 定義的函式中有一個隱式的額外行回傳 Unit。
假設您正在呼叫一個帶有回呼引數的函式fun foo(onComplete: (String)->Unit),并且您希望將回傳的值添加到 Set:
foo {
someMutableSet.add(it)
}
該add函式回傳一個我們在這里不關心的布林值。如果你必須記住這樣標記它會很煩人:
foo {
someMutableSet.add(it)
Unit
}
這種特殊處理不僅僅適用于 lambda。您也不必return Unit在每個回傳 Unit 的傳統函式的末尾添加一行。而且您也不必顯式地: Unit為函式簽名指定回傳型別。
uj5u.com熱心網友回復:
您Int沒有被強制轉換為Unit. 其實是反過來的。您的() -> Intlambda 被視為() -> Unitlambda。具體來說,來自關于 lambda 運算式的檔案(強調我的),
lambda 運算式的完整語法形式如下:
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x y }...
- 如果推斷的 lambda 的回傳型別不是
Unit,則 lambda 主體內的最后一個(或可能是單個)運算式被視為回傳值。
所以在你的例子中,
Animal<Unit>().extension { 2 2 }
{ 2 2 }不是回傳. _ Int這是一個回傳的 lambda Unit,即沒有任何價值。Kotlin 很樂意簡單地丟棄 lambda 的回傳值,如果它使型別推斷起作用的話。那是為了允許類似的事情
myButton.addEventListener { event ->
...
someFunctionThatHappensToReturnInt()
}
如果 lambdaInt僅僅因為我碰巧呼叫了一個回傳 的函式(用于副作用)而推斷出回傳型別,那將是非常煩人的Int,所以 Kotlin 會在必要時洗掉它。
如果你return明確地寫這個詞,你會強制引數的型別是,() -> Int并且會看到你期望的錯誤。
Animal<Unit>().extension { return 2 2; }
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/510454.html
標籤:科特林仿制药kotlin 扩展
下一篇:具有單維和多維陣列的可變引數
