Kotlin教學 | 從零開始學Kotlin | Kotlin入門 | CH5: 函數(Function)

函數

函數可以想像成是一個容器,存放一段旨在執行特定任務的程式碼。
它可以接受輸入參數,執行操作,並返回結果。
通常會將常用的功能寫成函數,這樣就不用每次同樣的計算或功能的都要重寫,只需要使用對應的函數名稱。

函數也分成兩個階段,分別是宣告使用

  • 宣告(聲明、實作、實現、定義等都有人稱呼):透過使用fun關鍵字來表示宣告函數和它的名稱,{表示函數宣告的開始,}表示函數宣告的結束,函數要執行的程式碼寫在大括號{}內。
  • 使用(調用、呼叫):指名函數名稱和提供參數給函數。

1. 宣告函數

參數列表在同一行:

fun functionName(param1: Type1, param2: Type2,): ReturnType {
    // 函數體
    return result
}

參數列表也可以在不同行:

fun functionName(
    param1: Type1,
    param2: Type2,
): ReturnType {
    // 函數體
    return result
}
  • fun 關鍵字用於聲明函數。
  • functionName 是函數名。
  • (param1: Type1, param2: Type2,) 是函數的參數列表,其中 param1param2 是參數名稱,Type1Type2 是它們的型別
    函數可以有任意數量的參數。
  • ReturnType 是函數返回值的型別
    如果函數不返回任何值,則可以省略返回型別,或使用 Unit 型別,這在 Kotlin 中等同於其他語言中的 void
  • 函數體包含在大括號 {} 中,這裡實現了函數的邏輯。
  • return 關鍵字用於返回函數的結果。result 是要返回的值,其型別要與 ReturnType 相匹配。

Example

fun double(x: Int): Int {
    return 2 * x
}

// 不返回任何值,使用 Unit 型別
fun printMessage(message: String): Unit {
    println(message)
}

// 不返回任何值,省略返回型別
fun printMessage(message: String) {
    println(message)
}

2. 調用函數

宣告函數後,可以通過其名稱來調用它,並提供必要的參數。

functionName(param1, param2)
  • functionName 是要調用的函數名稱。
  • (param1, param2) 是調用函數時傳遞給函數的實際參數。
    param1param2 要與函數宣告的參數型別相匹配。

Example

val result = double(2)

3. 參數命名和預設值

函數參數可以有預設值,這使得在調用函數時可以不用傳入該參數。

fun greet(name: String, greeting: String = "Hi") {
    println("$name, $greeting")
}

greet("Alice") // 使用默認的問候語 "Hi"
greet("Bob", "Hello") // 指定一個不同的問候語

指名參數

可以使用參數名來指定參數值。

greet(greeting = "Hello", name = "Charlie") // 使用命名參數調用函數

如果有預設值的參數在沒有預設值的參數前面,想要使用參數的預設值,要指名沒有預設值的參數。

fun greet(name: String = "Candy", greeting: String) {
    println("$greeting, $name")
}

greet(greeting = "Bye") // Candy, Bye

4. 單表達式函數

當函數體僅由一個表達式組成時,可以省略大括號並在等號(=)之後直接指定函數體。

fun double(x: Int): Int = x * 2

返回推斷

當函數返回型別可以推斷出來時,可以省略聲明返回型別。

fun double(x: Int) = x * 2

在這個例子中,由於表達式 x * 2 的結果顯然是 Int 型別,因此我們可以省略函數的返回型別聲明。
Kotlin會自動推斷出 double 函數返回 Int 型別。

5. 可變參數(Varargs)

在 Kotlin 中,可變參數(varargs)允許你將任意數量的參數傳遞給函數。

fun printAll(vararg messages: String) {
    for (m in messages) println(m)
}

你可以像這樣調用這個函數:

printAll("Alice", "Bob", "Charlie")

展開操作符(Spread Operator)

此外,Kotlin 還提供了一個稱為展開操作符(Spread Operator,即 *),它允許你將一個陣列傳遞給接受可變數量參數的函數,就好像是將陣列的每個元素單獨傳遞一樣。

val names = arrayOf("Alice", "Bob", "Charlie")
printAll(*names)

6. 函數的範圍

在 Kotlin 中,支持頂層函數、局部函數。

頂層函數

在 Kotlin 中,你可以直接在文件頂層定義函數,無需將函數封裝在類別中。

fun topLevelFunction() {
    println("這是一個頂層函數")
}

fun main() {
    println("Hello world")
    topLevelFunction()
}

局部函數

Kotlin 支持在函數內部定義局部函數,即一個函數內部包含另一個函數。

fun outerFunction() {
    fun localFunction() {
        println("這是一個局部函數")
    }
    
    localFunction()
}

閉包

局部函數可以訪問外層函數的局部變量(閉包)。

局部函數 localFunction 內部訪問了外層函數的局部變量 outerVariable,這展示了局部函數能夠訪問並操作外層函數中定義的變量,即形成了一個閉包(Closure)。
當調用 outerFunction 時,它又會調用 localFunction,後者會打印出訪問到的外層函數變量的值。

fun outerFunction() {
    val outerVariable = "我是外層函數的變量"
    
    fun localFunction() {
        println("訪問外層函數的局部變量:$outerVariable")
    }
    
    // 調用局部函數
    localFunction()
}

// 調用外層函數
outerFunction()

Reference

https://kotlinlang.org/docs/functions.html

發佈留言