Infix
Infix 函數(shù)是:
- 如果函數(shù)是成員函數(shù)或者extension 函數(shù)
- 如果只有一個(gè)參數(shù)
- 標(biāo)注了infix
// Define extension to Int
infix fun Int.shl(x: Int): Int {
...
}
// call extension function using infix notation
1 shl 2
// is the same as
1.shl(2)
函數(shù)默認(rèn)值
fun read(b: Array<Byte>, off: Int = 0, len: Int = b.size()) {
...
}
如果子類要覆蓋父類的方法,函數(shù)聲明的時(shí)候需要沿用父類的默認(rèn)值肩祥,不能重寫默認(rèn)值
//open class A {
open fun foo(i: Int = 10) { ... }
}
class B : A() {
override fun foo(i: Int) { ... } // no default value allowed
}
命名參數(shù)
fun reformat(str: String,
normalizeCase: Boolean = true,
upperCaseFirstLetter: Boolean = true,
divideByCamelHumps: Boolean = false,
wordSeparator: Char = ' ') {
...
}
reformat(str,
normalizeCase = true,
upperCaseFirstLetter = true,
divideByCamelHumps = false,
wordSeparator = '_'
)
Varargs
函數(shù)參數(shù)可以被標(biāo)記為vararg
后室,參數(shù)會(huì)被當(dāng)做數(shù)組:
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
}
只有一個(gè)參數(shù)能被標(biāo)記為vararg
,如果vararg
參數(shù)不是最后一個(gè)參數(shù)搭幻,其他參數(shù)只能通過命名參數(shù)來傳遞咧擂。
局部函數(shù)
局部函數(shù)是定義在函數(shù)內(nèi)部的函數(shù)逞盆,它可以訪問外部函數(shù)的變量
fun dfs(graph: Graph) {
fun dfs(current: Vertex, visited: Set<Vertex>) {
if (!visited.add(current)) return
for (v in current.neighbors)
dfs(v, visited)
}
dfs(graph.vertices[0], HashSet())
}
泛型函數(shù)
泛型函數(shù)將泛型參數(shù)放在函數(shù)名之前
fun <T> singletonList(item: T): List<T> {
// ...
}
Extension函數(shù)
向已有的對(duì)象添加函數(shù)檀蹋,函數(shù)里的this代表對(duì)象
fun MutableList<Int>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // 'this' corresponds to the list
this[index1] = this[index2]
this[index2] = tmp
}
高階函數(shù)
高階函數(shù)將其他函數(shù)作為參數(shù)傳入
fun <T> lock(lock: Lock, body: () -> T): T {
lock.lock()
try {
return body()
}
finally {
lock.unlock()
}
}
如果最后一個(gè)參數(shù)是函數(shù),而且傳入的是lambda函數(shù)云芦,則可以把lambda函數(shù)寫在括號(hào)外俯逾,如果傳入的是匿名函數(shù),則不能寫在括號(hào)外:
lock (lock) {
sharedResource.operation()
}
如果lambda函數(shù)只有一個(gè)參數(shù)舅逸,可以用it來指代
函數(shù)參數(shù)需要聲明函數(shù)的type:
fun <T> max(collection: Collection<T>, less: (T, T) -> Boolean): T? {
var max: T? = null
for (it in collection)
if (max == null || less(max, it))
max = it
return max
}
函數(shù)類型里也可以指定參數(shù)名稱
val compare: (x: T, y: T) -> Int = ...
匿名函數(shù)
fun(x: Int, y: Int): Int = x + y
如果是單行的表達(dá)式桌肴,返回值的類型可以推導(dǎo)出,可以省略琉历,如果是block坠七,那么返回值的類型需要指定,否則就是Unit
lambda表達(dá)式的return是退出外圍的函數(shù)旗笔,而匿名函數(shù)的return是退出自己
閉包
lambda表達(dá)式和匿名函數(shù)都可以訪問外圍作用域的變量彪置,與Java不同的是,Kotlin允許修改閉包里的變量(Java閉包的變量需要聲明為final)
帶Receiver的字面函數(shù)(好難理解)
你可以定義一個(gè)函數(shù)蝇恶,指定這個(gè)函數(shù)的Receiver拳魁,Receiver為一個(gè)類
sum : Int.(other: Int) -> Int
然后在這個(gè)類的實(shí)例上調(diào)用這個(gè)函數(shù)
1.sum(2)
inline 函數(shù)
inline 之前
lock(l) { foo() }
inline 之后
inline fun lock<T>(lock: Lock, body: () -> T): T {
// ...
}
==>
l.lock()
try {
foo()
}
finally {
l.unlock()
}
inline 會(huì)展開調(diào)用函數(shù)和lambda參數(shù),如果不想lambda參數(shù)被展開撮弧,可以在lambda參數(shù)前加上noinline
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
// ...
}
lambda表達(dá)式中不允許使用不帶標(biāo)簽的return語句(因?yàn)閘ambda中return是退出外圍的函數(shù)潘懊,這叫non-local return
)姚糊,但如果lambda是傳入到一個(gè)inline函數(shù)中,則可以return