Kotlin入坑(六)函式
函式宣告 使用 fun 關鍵字 引數使用 name: type
的形式表示 左邊是引數的名字 右邊是引數的型別,最後的冒號後面代表返回值的型別。如果這個函式沒有返回值可以省略或者使用Unit 代替
fun double(x: Int): Int {
return 2 * x
}
引數可以有預設值 比如上面的( x : Int = 0)
用法:
val result = double(2)
當函式返回單個表示式時,可以省略花括號並且在 = 符號之後指定程式碼體即可:
fun double(x: Int): Int = x * 2
可變數量的引數(Varargs
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
}
允許將可變數量的引數傳遞給函式:
val list = asList(1, 2, 3)
函式作用域
在 Kotlin 中函式可以在檔案頂層宣告,這意味著你不需要像一些語言如 Java、C# 或 Scala 那樣建立一個類來儲存一個函式。此外除了頂層函式,Kotlin 中函式也可以宣告在區域性作用域、作為成員函式以及擴充套件函式。
Kotlin 支援區域性函式,即一個函式在另一個函式內部:
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())
}
區域性函式可以訪問外部函式(即閉包)的區域性變數,所以在上例中,visited 可以是區域性變數:
fun dfs(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])
}
泛型函式 函式可以有泛型引數,通過在函式名前使用尖括號指定:
fun <T> singletonList(item: T): List<T> {
// ……
}
高階函式
高階函式是將函式用作引數或返回值的函式
Lambda 表示式
- lambda 表示式總是被大括號括著
- 其引數(如果有的話)在
->
之前宣告(引數型別可以省略) - 函式體(如果存在的話)在
->
後面
高階函式的另一個例子是 list中的map()方法
fun <T, R> List<T>.map(transform: (T) -> R): List<R> {
val result = arrayListOf<R>()
for (item in this)
result.add(transform(item))
return result
}
例子:
val ints = listOf<Int>(1,2,3,4,5,5)
//可以如下呼叫
val resmap = ints.map {
value -> value * 2
}
Log.i("resmap",resmap.toString());
//結果
12-18 13:54:32.147 9639-9639/com.chs.kotlintext I/resmap: [2, 4, 6, 8, 10, 10]
另一個有用的約定是,如果函式字面值只有一個引數, 那麼它的宣告可以省略(連同 ->),其名稱是 it。
所以上面的例子可以寫成
val resmap = ints.map {
it * 2
}
//返回值和上面一樣
12-18 14:00:13.812 10038-10038/com.chs.kotlintext I/resmap: [2, 4, 6, 8, 10, 10]
行內函數
使用 inline 關鍵字
內聯目前主要是應用在 函式引數是lambda表示式的程式碼中,可以提高高階函式的效率
inline fun <T> lock(lock: Lock, body: () -> T): T {
// ……
}
inline修飾符影響函式本身和傳給它的 lambda 表示式:所有這些都將內聯到呼叫處。如果有兩個以上的lambda引數,只想聯一個怎麼辦,就用到了 noinline 關鍵字
inline fun foo(inlined: () -> Unit, noinline notInlined: () -> Unit) {
// ……
}
協程
在 Kotlin 1.1+ 中協程是實驗性的
關於協程的內容很多
簡單例子
專案build.gradle檔案中加入下面引用
compile 'org.jetbrains.kotlinx:kotlinx-coroutines-core:0.20'
launch 在不阻塞當前執行緒的情況下啟動新協程,並將協程的引用作為Job返回。當作業被取消時,協程被取消。
launch { // 在後臺啟動新的協程並繼續
delay(1000L) // 非阻塞延遲1秒(預設時間單位是ms)
Log.i("launch","World") // 延遲後列印
}
Log.i("launch","Hello") // 主執行緒在協程延遲的時候繼續
列印結果:
12-18 16:52:25.827 17383-17383/com.chs.kotlintext I/launch: Hello
12-18 16:52:26.831 17383-17428/com.chs.kotlintext I/launch: World