2016-02-12 64 views
9

我有以下功能:() - >單位和(單位) - >單位類型有什麼區別?

fun <T, U> process(t: T, call: (U) -> Unit, map: (T) -> U) = call(map(t)) 

fun <T> processEmpty(t: T, call:() -> Unit) = process(t, call, {}) // error 

processEmpty沒有編制。錯誤消息是Type mismatch: inferred type is() -> kotlin.Unit but (kotlin.Unit) -> kotlin.Unit was expected。但是,如果我改變這個功能

fun <T> processEmpty2(t: T, call: (Unit) -> Unit) = process(t, call, {}) // OK 

那麼什麼是() -> Unit(Unit) -> Unit類型之間的區別?爲什麼第一個版本的processEmpty沒有編譯?

+0

我發現我認爲更好的方法來定義'processEmpty'函數:'fun processEmpty(t:T,call:() - > Unit)= process(t,{call()},{} )' – netimen

+0

是的,'{call()}'是一個參數(隱含'it')的正確函數,因此它可以作爲'(Unit) - > Unit'傳遞。 – hotkey

回答

19

Unit實際上是一個type that has exactly one value(值爲Unit本身;同樣,這也是它被命名爲Unit的原因)。它對應於Java中的void,但它不相同。

Kotlin編譯器將沒有聲明返回值的函數視爲Unit-returning functions,並且return Unit也可以省略。這就是爲什麼{ }是一個單位返回功能。

但是這不適用於參數。嚴格來說,當您使用Unit自變量或(Unit) -> Unit函數變量聲明函數時,必須在呼叫站點傳遞Unit類型的參數。唯一通過的值是Unit

沒有指定參數(如{ doSomething() })的lambda被視爲不帶參數的函數,也不帶有單個隱式參數it。您可以使用{ }作爲() -> Unit(Unit) -> Unit

,該呼叫網站,上面說,Unit將被傳遞:

val f: (Unit) -> Unit = { println("Hello") } 

f(Unit) // the only valid call 

() -> Unit功能並不需要一個參數傳遞:

val f:() -> Unit = { println("Hello") } 

f() // valid call 


在你例如,類型推斷髮生如下:

fun <T, U> process(t: T, call: (U) -> Unit, map: (T) -> U) = call(map(t)) 

fun <T> processEmpty(t: T, call:() -> Unit) = process(t, call, {}) // error 
  1. map: (T) -> U = { },因此U的替代爲Unit{ }返回。因此call應爲(Unit) -> Unit
  2. call:() -> Unit這與(Unit) -> Unit不一樣,如上所述。錯誤。