為什麼Kotlin中沒有使用Void作為返回型別
theme: cyanosis highlight: androidstudio
為什麼Kotlin中沒有使用Void作為返回型別
持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第26天,點選檢視活動詳情
Kotlin是一種帶有很多語法糖的語言。儘管它是一種面向物件的語言。但是在Kotlin中是函式作為一等公民,而不是物件。這一個特性就決定了它可以使用函式進行傳遞和返回。因此,Kotlin中的高階函式應用就很廣。高階函式至少就需要一個函式作為引數,或者返回一個函式。
在Kotlin中沒有不敢回任何內容的函式。在Java中我們可以使用void
來表示函式不返回任何內容,但是在Kotlin中的函式總是要返回一些內容。如果我們沒有在明明函式宣告中明確的指定返回型別,或者沒有在Lambda函式中明確返回任何內容,它就會返回Unit
。下面的示例實際時相同的
```kotlin fun funcionNoReturnAnything(){
} fun funcionNoReturnAnything():Unit{
} ```
或者是在lambda函式體中最後一個值會作為返回值返回,如果沒有明確返回,就會預設返回Unit
```kotlin view.setOnclickListener{
}
view.setOnclickListener{
Unit
}
```
儘管他們在寫法上會有一些不同,但是Unit同Java中的Void
在含義上都是一樣的,如果在Kotlin程式碼中嗲用Java中不會返回任何內容的方法,將返回的是Unit,而不是Void。在Kotlin中Unit是一個單例描述者函式不會返回任何有用的值
我們試著去建立一個Kotlin中的高階函式,看看反編譯背後的Java程式碼是怎麼實現的
kotlin
fun run(block:() -> Unit){
block()
}
run
函式接受一個名為“block”的引數,該引數具有函式型別“() -> Unit”,這意味著塊本身是一個不帶引數並返回 Unit 的函式。反編譯的Java程式碼如下:
java
public static final void run(@NotNull Function0 block){
Instrinsics.checkNotNullParameter(block,"block");
block.invoke();
}
在底層,函式run
採用一個名為block
的引數,就像在原始 Kotlin 程式碼中一樣。但是,引數的型別在這裡稱為“Function0”。由於我們在 Java 中實際上沒有函式型別,因此使用智慧實現來提供與 Java 的完整互操作性。看原始碼就可以理解了
java
public interface Function0<out R>:Funciton<R>{
public operator fun invoke():R
}
可以看出Fuction0是一個泛型介面,它表示一個不帶引數並返回泛型型別 R 的函式型別。該介面有一個方法“invoke”,在呼叫此函式時會呼叫該方法。Kotlin 的函式型別被實現為這個通用介面的匿名物件,其中函式體被實現為“invoke”方法的主體。對於引數最多為 22 的函式,還有其他類似的介面。
為了保持與預設情況下沒有函式型別並且需要面向物件的方法(建立已定義介面的匿名類的物件)來建立值儲存函式的 Java 的互操作性,需要一個類來使編譯器能夠在下面使用泛型,同時保持“不返回(有用的)值”的概念
此外,每當我們建立 lambda、傳遞 noinline 函式作為引數或建立對函式型別的引用時,都會建立相應介面的匿名類的物件。每當我們想要傳遞函式時,Kotlin 都會簡單地將我們從 Java 的樣板檔案中拯救出來。當我們通過在其引用名稱後新增括號來呼叫函式時,將呼叫前面提到的介面之一的運算子“invoke”方法。運算子函式可以通過相應的運算子呼叫,invoke 函式對應於“invoke operator” =>()。您可以在下面看到兩種呼叫函式型別的方法:
kotlin
fun run(block:() -> Unit){
block()
//或者是使用這種方式都是允許的
block.invoke()
}