函數(shù)
函數(shù)聲明
Kotlin 中的函數(shù)使用 fun 關(guān)鍵字聲明,其code表現(xiàn)形式:
fun double(x: Int): Int {
return 2 * x
}
函數(shù)用法
調(diào)用函數(shù)使用傳統(tǒng)的方法:
val result = double(2)
調(diào)用成員函數(shù)使用點表示法
Stream().read() // 創(chuàng)建類 Stream 實例并調(diào)用 read()
val funDemo = FunDemo()
val result = funDemo.double(2)
參數(shù)
函數(shù)參數(shù)使用 Pascal 表示法定義,即 name: type昆咽。參數(shù)用逗號隔開。每個參數(shù)必須有顯式類型:
fun powerOf(number: Int, exponent: Int) { /*......*/ }
默認參數(shù)
函數(shù)參數(shù)可以有默認值,當省略相應的參數(shù)時使用默認值腹暖。與其他語言相比,這可以減少重載數(shù)量:
fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size) { /*......*/ }
默認值通過類型后面的 = 及給出的值來定義。
覆蓋方法總是使用與基類型方法相同的默認參數(shù)值亩鬼。 當覆蓋一個帶有默認參數(shù)值的方法時,必須從簽名
中省略默認參數(shù)值:
open class A {
open fun foo(i: Int = 10) { /*......*/ }
}
class B : A() {
override fun foo(i: Int) { /*......*/ }
}
如果一個默認參數(shù)在一個無默認值的參數(shù)之前,那么該默認值只能通過使用具名參數(shù)調(diào)用該函數(shù)來使
用:
fun foo(bar: Int = 0, baz: Int) { /*......*/ }
foo(baz = 1) // 使用默認值 bar = 0
如果在默認參數(shù)之后的最后一個參數(shù)是 lambda 表達式,那么它既可以作為具名參數(shù)在括號內(nèi)傳入,也
可以在括號外傳入:
fun foo(bar: Int = 0, baz: Int = 1, qux: () -> Unit) { /*......*/ }
foo(1) { println("hello") }
// 使用默認值 baz = 1
foo(qux = { println("hello") }) // 使用兩個默認值 bar = 0 與 baz = 1
foo { println("hello") } // 使用兩個默認值 bar = 0 與 baz = 1
具名參數(shù)
可以在調(diào)用函數(shù)時使用具名的函數(shù)參數(shù)。當一個函數(shù)有大量的參數(shù)或默認參數(shù)時這會非常方便爽丹。
給定以下函數(shù):
fun reformat(str: String,
normalizeCase: Boolean = true,
upperCaseFirstLetter: Boolean = true,
divideByCamelHumps: Boolean = false,
wordSeparator: Char = ' ') {
/*......*/
}
我們可以使用默認參數(shù)來調(diào)用它:
reformat(str)
然而,當使用非默認參數(shù)調(diào)用它時,該調(diào)用看起來就像:
reformat(str, true, true, false, '_')
使用具名參數(shù)我們可以使代碼更具有可讀性:
reformat(str,
normalizeCase = true,
upperCaseFirstLetter = true,
divideByCamelHumps = false,
wordSeparator = '_'
)
并且如果我們不需要所有的參數(shù):
reformat(str, wordSeparator = '_')
當一個函數(shù)調(diào)用混用位置參數(shù)與具名參數(shù)時,所有位置參數(shù)都要放在第一個具名參數(shù)之前粤蝎。
例如,允許調(diào)用 f(1, y = 2) 但不允許 f(x = 1, 2) 。
當一個函數(shù)調(diào)用混用位置參數(shù)與具名參數(shù)時,所有位置參數(shù)都要放在第一個具名參數(shù)之前碑宴。
例如,允許
調(diào)用 f(1, y = 2) 但不允許 f(x = 1, 2) 延柠。
可以通過使用星號操作符將可變數(shù)量參數(shù)(vararg) 以具名形式傳入:
fun foo(vararg strings: String) { /*......*/ }
foo(strings = *arrayOf("a", "b", "c"))
//對于 JVM 平臺:在調(diào)用 Java 函數(shù)時不能使用具名參數(shù)語法,因為 Java 字節(jié)碼并不總是保留函數(shù)
參數(shù)的名稱捕仔。
返回 Unit 的函數(shù)
如果一個函數(shù)不返回任何有用的值,它的返回類型是 Unit 。 Unit 是一種只有一個值? Unit 的類
型钓葫。這個值不需要顯式返回:
fun printHello(name: String?): Unit {
if (name != null)
println("Hello ${name}")
else
println("Hi there!")
// `return Unit` 或者 `return` 是可選的
}
Unit 返回類型聲明也是可選的票顾。
上面的代碼等同于:
fun printHello(name: String?) { ...... }
單表達式函數(shù)
當函數(shù)返回單個表達式時,可以省略花括號并且在 = 符號之后指定代碼體即可:
fun double(x: Int): Int = x * 2
當返回值類型可由編譯器推斷時,顯式聲明返回類型是可選的:
fun double(x: Int) = x * 2
顯式返回類型
具有塊代碼體的函數(shù)必須始終顯式指定返回類型,除非他們旨在返回 Unit ,在這種情況下它是可選
的。 Kotlin 不推斷具有塊代碼體的函數(shù)的返回類型,因為這樣的函數(shù)在代碼體中可能有復雜的控制流,
并且返回類型對于讀者(有時甚至對于編譯器)是不明顯的。
可變數(shù)量的參數(shù)(Varargs)
函數(shù)的參數(shù)(通常是最后一個)可以用 vararg 修飾符標記:
fun <T> asList(vararg ts: T): List<T> {
val result = ArrayList<T>()
for (t in ts) // ts is an Array
result.add(t)
return result
}
允許將可變數(shù)量的參數(shù)傳遞給函數(shù):
val list = asList(1, 2, 3)
在函數(shù)內(nèi)部,類型 T 的 vararg 參數(shù)的可?方式是作為 T 數(shù)組,即上例中的 ts 變量具有類型
Array <out T> 芹务。
只有一個參數(shù)可以標注為 vararg 。
如果 vararg 參數(shù)不是列表中的最后一個參數(shù), 可以使用具名參
數(shù)語法傳遞其后的參數(shù)的值,或者,如果參數(shù)具有函數(shù)類型,則通過在括號外部傳一個 lambda佳晶。
當我們調(diào)用 vararg -函數(shù)時,我們可以一個接一個地傳參,例如 asList(1, 2, 3) ,或者,如果我們
已經(jīng)有一個數(shù)組并希望將其內(nèi)容傳給該函數(shù),我們使用伸展(spread) 操作符(在數(shù)組前面加 * ):
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
中綴表示法
標有 infix 關(guān)鍵字的函數(shù)也可以使用中綴表示法(忽略該調(diào)用的點與圓括號)調(diào)用轿秧。
中綴函數(shù)必須滿足
以下要求:
- 它們必須是成員函數(shù)或擴展函數(shù);
- 它們必須只有一個參數(shù);
- 其參數(shù)不得接受可變數(shù)量的參數(shù)且不能有默認值。
infix fun Int.shl(x: Int): Int { ...... }
// 用中綴表示法調(diào)用該函數(shù)
1 shl 2
// 等同于這樣
1.shl(2)
中綴函數(shù)調(diào)用的優(yōu)先級低于算術(shù)操作符陨仅、類型轉(zhuǎn)換以及 rangeTo 操作符灼伤。 以下表達式是等價
的:
— 1 shl 2 + 3 等價于 1 shl (2 + 3)
— 0 until n * 2 等價于 0 until (n * 2)
— xs union ys as Set<> 等價于 xs union (ys as Set<>)
另一方面,中綴函數(shù)調(diào)用的優(yōu)先級高于布爾操作符 && 與 ||撞鹉、 is- 與 in- 檢測以及其他一些操
作符鸟雏。
這些表達式也是等價的:
— a && b xor c 等價于 a && (b xor c)
— a xor b in c 等價于 (a xor b) in c
請注意,中綴函數(shù)總是要求指定接收者與參數(shù)览祖。
當使用中綴表示法在當前接收者上調(diào)用方法時,需要顯
式使用 this ;不能像常規(guī)方法調(diào)用那樣省略孝鹊。
這是確保非模糊解析所必需的。
//infix 美 [in`fiks. `in-. `infiks]
//vt. 把…印入展蒂;把…插進
//n. 中綴又活;插入詞
class MyStringCollection {
infix fun add(s: String) { /*......*/ }
fun build() {
this add "abc" // 正確
add("abc") // 正確
//add "abc" // 錯誤:必須指定接收者
}
}
函數(shù)作用域
在 Kotlin 中函數(shù)可以在文件頂層聲明,這意味著你不需要像一些語言如 Java苔咪、C# 或 Scala 那樣需要創(chuàng)
建一個類來保存一個函數(shù)。
此外除了頂層函數(shù),Kotlin 中函數(shù)也可以聲明在局部作用域柳骄、作為成員函數(shù)
以及擴展函數(shù)团赏。
局部函數(shù)
Kotlin 支持局部函數(shù),即一個函數(shù)在另一個函數(shù)內(nèi)部:
fun dfs(graph: Graph) {
fun dfs(current: Vertex, visited: MutableSet<Vertex>) {
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v, visited)
}
dfs(graph.vertices[0], HashSet())
}
局部函數(shù)可以訪問外部函數(shù)(即閉包)的局部變量,所以在上例中,visited 可以是局部變量:
fun dfs1(graph: Graph) {
val visited = HashSet<Vertex>()
fun dfs(current: Vertex) {
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v)
}
dfs(graph.vertices[0])
}
成員函數(shù)
成員函數(shù)是在類或?qū)ο髢?nèi)部定義的函數(shù):
class Sample() {
fun foo() { print("Foo") }
}
成員函數(shù)以點表示法調(diào)用:
Sample().foo() // 創(chuàng)建類 Sample 實例并調(diào)用 foo
高階函數(shù)與 lambda 表達式
Kotlin 函數(shù)都是 頭等的,這意味著它們可以存儲在變量與數(shù)據(jù)結(jié)構(gòu)中、作為參數(shù)傳遞給其他高階函數(shù)以
及從其他高階函數(shù)返回。可以像操作任何其他非函數(shù)值一樣操作函數(shù)。
為促成這點,作為一?靜態(tài)類型編程語言的 Kotlin 使用一系列函數(shù)類型來表示函數(shù)并提供一組特定的
語言結(jié)構(gòu),例如 lambda 表達式。
高階函數(shù)
高階函數(shù)是將函數(shù)用作參數(shù)或返回值的函數(shù)。
一個不錯的示例是集合的函數(shù)式?格的 fold, 它接受一個初始累積值與一個接合函數(shù),并通過將當前
累積值與每個集合元素連續(xù)接合起來代入累積值來構(gòu)建返回值:
/*
combine
美 [kEm`bain] vt. 使化合丰捷;使聯(lián)合停巷,使結(jié)合 vi. 聯(lián)合硼被,結(jié)合;化合 n. 聯(lián)合收割機;聯(lián)合企業(yè)
accumulator
accumulator [??kju?mj?le?t?(r)] n. 蓄電池;[計] 累加器五嫂;積聚者
*/
fun <T, R> Collection<T>.fold(
initial: R,
combine: (acc: R, nextElement: T) -> R
): R {
var accumulator: R = initial
for (element: T in this) {
accumulator = combine(accumulator, element)
}
return accumulator
}
在上述代碼中,參數(shù) combine 具有函數(shù)類型 (R, T) -> R ,因此 fold 接受一個函數(shù)作為參數(shù), 該
函數(shù)接受類型分別為 R 與 T 的兩個參數(shù)并返回一個 R 類型的值。 在 for-循環(huán)內(nèi)部調(diào)用該函數(shù),然后
將其返回值賦值給 accumulator 。
為了調(diào)用 fold ,需要傳給它一個函數(shù)類型的實例作為參數(shù),而在高階函數(shù)調(diào)用處, (下文詳述的)lambda 表達 式廣泛用于此目的。
fun testFold() {
val items = listOf(1, 2, 3, 4, 5)
// Lambdas 表達式是花括號括起來的代碼塊槽棍。
items.fold(0, {
// 如果一個 lambda 表達式有參數(shù),前面是參數(shù),后跟“->”
acc: Int, i: Int ->
print("acc = $acc, i = $i, ")
val result = acc + i
println("result = $result")
// lambda 表達式中的最后一個表達式是返回值:
result
})
// lambda 表達式的參數(shù)類型是可選的,如果能夠推斷出來的話:
val joinedToString = items.fold("Elements:", { acc, i -> acc + " " + i })
// 函數(shù)引用也可以用于高階函數(shù)調(diào)用:
val product = items.fold(1, Int::times)
}
以下各節(jié)會更詳細地解釋上文提到的這些概念。
函數(shù)類型
Kotlin 使用類似 (Int) -> String 的一系列函數(shù)類型來處理函數(shù)的聲明:
val onClick: () -> Unit = ...... 。`
這些類型具有與函數(shù)簽名相對應的特殊表示法,即它們的參數(shù)和返回值:
- 所有函數(shù)類型都有一個圓括號括起來的參數(shù)類型列表以及一個返回類型:
(A, B) -> C
表示接受
類型分別為 A 與 B 兩個參數(shù)并返回一個 C 類型值的函數(shù)類型惜纸。 參數(shù)類型列表可以為空,如
() -> A 古瓤。 Unit 返回類型不可省略。
- 函數(shù)類型可以有一個額外的接收者類型,它在表示法中的點之前指定: 類型
A.(B) -> C
表示可以在 A 的接收者對象上以一個 B 類型參數(shù)來調(diào)用并返回一個 C 類型值的函數(shù)主届。 帶有接收者的函
數(shù)字面值通常與這些類型一起使用橡庞。
A.(B) -> C 表示可
以在 A 的接收者對象上以一個 B 類型參數(shù)來調(diào)用并返回一個 C 類型值的函數(shù)。這句話不理解
//這樣的函數(shù)字面值的類型是一個帶有接收者的函數(shù)類型:
//下面是定義參數(shù)
sum : Int.(other: Int) -> Int
//該函數(shù)字面值可以這樣調(diào)用秉剑,就像它是接收者對象上的一個方法一樣:
1.sum(2)
- 掛起函數(shù)屬于特殊種類的函數(shù)類型,它的表示法中有一個 suspend 修飾符 ,例如
suspend () -> Unit 或者 suspend A.(B) -> C 。
函數(shù)類型表示法可以選擇性地包含函數(shù)的參數(shù)名: (x: Int, y: Int) -> Point 床嫌。 這些名稱可用于表明參數(shù)的含義。
如需將函數(shù)類型指定為可空,請使用圓括號: ((Int, Int) -> Int)?贯要。
函數(shù)類型可以使用圓括號進行接合: (Int) -> ((Int) -> Unit)
箭頭表示法是右結(jié)合的, (Int) -> (Int) -> Unit 與前述示例等價,但不等于 ((Int) ->
(Int)) -> Unit京郑。
還可以通過使用類型別名給函數(shù)類型起一個別稱:
typealias ClickHandler = (Button, ClickEvent) -> Unit
函數(shù)類型實例化
有幾種方法可以獲得函數(shù)類型的實例:
- 使用函數(shù)字面值的代碼塊,采用以下形式之一:
- lambda 表達式: { a, b -> a + b } ,
- 匿名函數(shù): fun(s: String): Int { return s.toIntOrNull() ?: 0 }
帶有接收者的函數(shù)字面值可用作帶有接收者的函數(shù)類型的值。
- 使用已有聲明的可調(diào)用引用:
- 頂層绪抛、局部店雅、成員、擴展函數(shù): ::isOdd 、 String::toInt ,
- 頂層痴鳄、成員、擴展屬性: List<Int>::size ,
- 構(gòu)造函數(shù): ::Regex
這包括指向特定實例成員的綁定的可調(diào)用引用: foo::toString 缸夹。
- 使用實現(xiàn)函數(shù)類型接口的自定義類的實例:
class IntTransformer: (Int) -> Int {
override operator fun invoke(x: Int): Int = TODO()
}
val intFunction: (Int) -> Int = IntTransformer()
如果有足夠信息,編譯器可以推斷變量的函數(shù)類型:
val a = { i: Int -> i + 1 } // 推斷出的類型是 (Int) -> Int
帶與不帶接收者的函數(shù)類型非字面值可以互換,其中接收者可以替代第一個參數(shù),反之亦然痪寻。
例如,(A,
B) -> C 類型的值可以傳給或賦值給期待 A.(B) -> C 的地方,反之亦然:
val repeatFun: String.(Int) -> String = { times -> this.repeat(times) }
val twoParameters: (String, Int) -> String = repeatFun // OK
fun runTransformation(f: (String, Int) -> String): String {
return f("hello", 3)
}
val result = runTransformation(repeatFun) // OK
請注意,默認情況下推斷出的是沒有接收者的函數(shù)類型,即使變量是通過擴展函數(shù)引用來初始化的。 如需改變這點,請顯式指定變量類型
函數(shù)類型實例調(diào)用
函數(shù)類型的值可以通過其 invoke(......) 操作符調(diào)用: f.invoke(x) 或者直接 f(x) 虽惭。
如果該值具有接收者類型,那么應該將接收者對象作為第一個參數(shù)傳遞橡类。 調(diào)用帶有接收者的函數(shù)類型值 的另一個方式是在其前面加上接收者對象, 就好比該值是一個擴展函數(shù): 1.foo(2) ,例如
val stringPlus: (String, String) -> String = String::plus
val intPlus: Int.(Int) -> Int = Int::plus
println(stringPlus.invoke("<-", "->"))
println(stringPlus("Hello, ", "world!"))
println(intPlus.invoke(1, 1))
println(intPlus(1, 2))
println(2.intPlus(3)) // 類擴展調(diào)用
Lambda 表達式與匿名函數(shù)
lambda 表達式與匿名函數(shù)是“函數(shù)字面值”,即未聲明的函數(shù), 但立即做為表達式傳遞⊙看剑考慮下面的例子:
max(strings, { a, b -> a.length < b.length })
函數(shù) max 是一個高階函數(shù),它接受一個函數(shù)作為第二個參數(shù)顾画。 其第二個參數(shù)是一個表達式,它本身是一個函數(shù),即函數(shù)字面值,它等價于以下具名函數(shù):
fun compare(a: String, b: String): Boolean = a.length < b.length
Lambda 表達式語法
Lambda 表達式的完整語法形式如下:
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
lambda 表達式總是括在花括號中, 完整語法形式的參數(shù)聲明放在花括號內(nèi),并有可選的類型標注, 函數(shù)體跟在一個 -> 符號之后取劫。如果推斷出的該 lambda 的返回類型不是 Unit ,那么該 lambda 主體中 的最后一個(或可能是單個)表達式會視為返回值。
如果我們把所有可選標注都留下,看起來如下:
val sum = { x, y -> x + y }
傳遞末尾的 lambda 表達式
在 Kotlin 中有一個約定:如果函數(shù)的最后一個參數(shù)是函數(shù),那么作為相應參數(shù)傳入的 lambda 表達式可以放在圓括號之外
val product = items.fold(1) { acc, e -> acc * e }
這種語法也稱為拖尾 lambda 表達式 研侣。
如果該 lambda 表達式是調(diào)用時唯一的參數(shù),那么圓括號可以完全省略:
run { println("...") }
it:單個參數(shù)的隱式名稱
一個 lambda 表達式只有一個參數(shù)是很常?的谱邪。如果編譯器自己可以識別出簽名,也可以不用聲明唯一的參數(shù)并忽略 -> 。 該參數(shù)會隱式聲明為 it :
//it 用在 lambda 表達式內(nèi)部來隱式引用其參數(shù)
ints.filter { it > 0 } // 這個字面值是“(it: Int) -> Boolean”類型的
從 lambda 表達式中返回一個值
我們可以使用限定的返回語法從 lambda 顯式返回一個值庶诡。 否則,將隱式返回最后一個表達式的值惦银。
因此,以下兩個片段是等價的
ints.filter {
val shouldFilter = it > 0
shouldFilter
}
ints.filter {
val shouldFilter = it > 0
return@filter shouldFilter
}
這一約定連同在圓括號外傳遞 lambda 表達式一起支持 LINQ-?格 的代碼:
strings.filter { it.length == 5 }.sortedBy { it }.map { it.toUpperCase() }
下劃線用于未使用的變量(自 1.1 起)
如果 lambda 表達式的參數(shù)未使用,那么可以用下劃線取代其名稱:
map.forEach { _, value -> println("$value!") }
在 lambda 表達式中解構(gòu)(自 1.1 起)
你可以對 lambda 表達式參數(shù)使用解構(gòu)聲明語法。 如果 lambda 表達式具有 Pair 類型(或者
Map.Entry 或任何其他具有相應 componentN 函數(shù)的類型)的參數(shù),那么可以通過將它們放在括號中來引入多個新參數(shù)來取代單個新參數(shù):
map.mapValues { entry -> "${entry.value}!" }
map.mapValues { (key, value) -> "$value!" }
注意聲明兩個參數(shù)和聲明一個解構(gòu)對來取代單個參數(shù)之間的區(qū)別:
{ a //-> ...... } //一個參數(shù)
{ a, b //-> ...... } // 兩個參數(shù)
{ (a, b) //-> ...... }// 一個解構(gòu)對
{ (a, b), c //-> ...... } // 一個解構(gòu)對以及其他參數(shù)
如果解構(gòu)的參數(shù)中的一個組件未使用,那么可以將其替換為下劃線,以避免編造其名稱:
map.mapValues { (_, value) -> "$value!" }
你可以指定整個解構(gòu)的參數(shù)的類型或者分別指定特定組件的類型:
map.mapValues { (_, value): Map.Entry<Int, String> -> "$value!" }
map.mapValues { (_, value: String) -> "$value!" }
匿名函數(shù)
上面提供的 lambda 表達式語法缺少的一個東西是指定函數(shù)的返回類型的能力末誓。
在大多數(shù)情況下,這是不必要的扯俱。因為返回類型可以自動推斷出來。然而,如果確實需要顯式指定,可以使用另一種語法: 匿名函數(shù) 基显。
fun(x: Int, y: Int): Int = x + y
匿名函數(shù)看起來非常像一個常規(guī)函數(shù)聲明,除了其名稱省略了蘸吓。其函數(shù)體可以是表達式(如上所示)或代碼塊:
fun(x: Int, y: Int): Int {
return x + y
}
參數(shù)和返回類型的指定方式與常規(guī)函數(shù)相同,除了能夠從上下文推斷出的參數(shù)類型可以省略:
ints.filter(fun(item) = item > 0)
匿名函數(shù)的返回類型推斷機制與正常函數(shù)一樣:對于具有表達式函數(shù)體的匿名函數(shù)將自動推斷返回類型,而具有代碼塊函數(shù)體的返回類型必須顯式指定(或者已假定為 Unit )。
請注意,匿名函數(shù)參數(shù)總是在括號內(nèi)傳遞撩幽。 允許將函數(shù)留在圓括號外的簡寫語法僅適用于 lambda 表達式库继。
Lambda表達式與匿名函數(shù)之間的另一個區(qū)別是非局部返回的行為。一個不帶標簽的 return 語句總是在用 fun 關(guān)鍵字聲明的函數(shù)中返回窜醉。這意味著 lambda 表達式中的 return 將從包含它的函數(shù)返回,而匿名函數(shù)中的 return 將從匿名函數(shù)自身返回.
閉包
Lambda 表達式或者匿名函數(shù)(以及局部函數(shù)和對象表達式) 可以訪問其 閉包 ,即在外部作用域中聲明的變量宪萄。 在 lambda 表達式中可以修改閉包中捕獲的變量:
var sum = 0
ints.filter { it > 0 }.forEach {
sum += it
}
print(sum)
帶有接收者的函數(shù)字面值
帶有接收者的函數(shù)類型,例如 A.(B) -> C ,可以用特殊形式的函數(shù)字面值實例化? 帶有接收者的函數(shù)字面值。
如上所述,Kotlin 提供了調(diào)用帶有接收者(提供接收者對象)的函數(shù)類型實例的能力榨惰。
在這樣的函數(shù)字面值內(nèi)部,傳給調(diào)用的接收者對象成為隱式的this,以便訪問接收者對象的成員而無需任何額外的限定符,亦可使用 this 表達式 訪問接收者對象拜英。這種行為與擴展函數(shù)類似,擴展函數(shù)也允許在函數(shù)體內(nèi)部訪問接收者對象的成員。這里有一個帶有接收者的函數(shù)字面值及其類型的示例,其中在接收者對象上調(diào)用了 plus :
val sum: Int.(Int) -> Int = { other -> plus(other) }
匿名函數(shù)語法允許你直接指定函數(shù)字面值的接收者類型琅催。 如果你需要使用帶接收者的函數(shù)類型聲明一個變量,并在之后使用它,這將非常有用居凶。
val sum = fun Int.(other: Int): Int = this + other
當接收者類型可以從上下文推斷時,lambda 表達式可以用作帶接收者的函數(shù)字面值。 One of the most important examples of their usage is type-safe builders:
class HTML {
fun body() { ...... }
}
fun html(init: HTML.() -> Unit): HTML {
val html = HTML() // 創(chuàng)建接收者對象
html.init() // 將該接收者對象傳給該 lambda
return html
}
html { // 帶接收者的 lambda 由此開始
body() // 調(diào)用該接收者對象的一個方法
}