1. 程式人生 > >Kotlin入坑(六)函式

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