程式設計人員的 Kotlin 新手上路課程 3:函式

這個程式碼研究室是「程式設計人員的 Kotlin 新手上路課程」的一部分。如果您按部就班完成程式碼研究室,就能充分體驗到本課程的價值。視您的知識多寡而定,您或許能略過某些部分。本課程適用於熟悉物件導向語言,且想學習 Kotlin 的程式設計師。

簡介

在本程式碼研究室中,您將建立 Kotlin 程式,並瞭解 Kotlin 中的函式,包括參數、篩選器、lambda 和精簡函式的預設值。

本課程的設計目標是協助您累積知識,但各單元之間彼此半獨立,因此您可以略過熟悉的部分,不必建構單一範例應用程式。為將這些範例連結在一起,許多範例都使用水族館主題。如要查看完整的魚缸故事,請參閱 Udacity 的程式設計人員 Kotlin 新手上路課程

必備知識

  • 現代物件導向靜態型別程式設計語言的基礎知識
  • 至少一種語言的類別、方法和例外狀況處理程式設計
  • 如何在 IntelliJ IDEA 中使用 Kotlin 的 REPL (Read-Eval-Print Loop)
  • Kotlin 的基本概念,包括型別、運算子和迴圈

本程式碼研究室適用於熟悉物件導向語言,且想進一步瞭解 Kotlin 的程式設計師。

課程內容

  • 如何在 IntelliJ IDEA 中使用 main() 函式和引數建立程式
  • 如何使用預設值和精簡函式
  • 如何為清單套用篩選條件
  • 如何建立基本 lambda 和高階函式

學習內容

  • 使用 REPL 試用一些程式碼。
  • 使用 IntelliJ IDEA 建立基本 Kotlin 程式。

在這項工作中,您將建立 Kotlin 程式並瞭解 main() 函式,以及如何從指令列將引數傳遞至程式。

您可能還記得在先前的程式碼實驗室中,您在 REPL 中輸入的 printHello() 函式:

fun printHello() {
    println ("Hello World")
}

printHello()
⇒ Hello World

您可以使用 fun 關鍵字定義函式,後面加上函式名稱。與其他程式設計語言一樣,括號 () 用於函式引數 (如有)。大括號 {} 會框住函式的程式碼。這個函式不會傳回任何內容,因此沒有傳回類型。

步驟 1:建立 Kotlin 檔案

  1. 開啟 IntelliJ IDEA。
  2. IntelliJ IDEA 左側的「Project」窗格會顯示專案檔案和資料夾清單。找到「Hello Kotlin」底下的「src」src資料夾,然後按一下滑鼠右鍵。(您應該已在上一個程式碼研究室中建立「Hello Kotlin」專案)。
  3. 依序選取「New」>「Kotlin File / Class」
  4. 將「Kind」保留為「File」,並將檔案命名為「Hello」
  5. 按一下「確定」

現在 src 資料夾中有名為 Hello.kt 的檔案。

步驟 2:新增程式碼並執行程式

  1. 與其他語言一樣,Kotlin 的 main() 函式會指定執行作業的進入點。任何指令列引數都會以字串陣列的形式傳遞。

    Hello.kt 檔案中輸入或貼上下列程式碼:
fun main(args: Array<String>) {
    println("Hello, world!")
}

與先前的 printHello() 函式一樣,這個函式沒有 return 陳述式。Kotlin 中的每個函式都會傳回某些內容,即使未明確指定也是如此。因此,像 main() 函式這樣的函式會傳回 kotlin.Unit 型別,這是 Kotlin 表示沒有值的方式。

  1. 如要執行程式,請按一下「main()」函式左側的綠色三角形。從選單中選取「Run 'HelloKt'」
  2. IntelliJ IDEA 會編譯並執行程式。結果會顯示在底部的記錄窗格中,如下所示。

步驟 3:將引數傳遞至 main()

由於您是從 IntelliJ IDEA 執行程式,而不是從指令列執行,因此需要以稍微不同的方式指定程式的任何引數。

  1. 依序選取「Run」>「Edit Configurations」。「Run/Debug Configurations」視窗隨即開啟。
  2. 在「程式引數」欄位中輸入 Kotlin!
  3. 按一下「確定」

步驟 4:變更程式碼以使用字串範本

字串範本會在字串中插入變數或運算式,而 $ 則會指定字串的哪個部分是變數或運算式。大括號 {} 會框住運算式 (如有)。

  1. Hello.kt 中,將問候訊息變更為使用傳遞至程式的第一個引數 args[0],而非 "world"
fun main(args: Array<String>) {
    println("Hello, ${args[0]}")
}
  1. 執行程式,輸出內容會包含您指定的引數。
⇒ Hello, Kotlin!

在本工作中,您將瞭解 Kotlin 中幾乎所有項目都有值的原因,以及這項特點的實用性。

其他語言則有陳述式,也就是沒有值的程式碼行。在 Kotlin 中,幾乎所有內容都是運算式,而且都有值,即使該值為 kotlin.Unit 也不例外。

  1. Hello.kt 中,於 main() 內編寫程式碼,將 println() 指派給名為 isUnit 的變數,然後列印該變數。(println() 不會傳回值,因此會傳回 kotlin.Unit)。
// Will assign kotlin.Unit
val isUnit = println("This is an expression")
println(isUnit)
  1. 執行程式。第一個 println() 會列印字串 "This is an expression"。第二個 println() 會列印第一個 println() 陳述式的值,也就是 kotlin.Unit
⇒ This is an expression
kotlin.Unit
  1. 宣告名為 temperatureval,並將其初始化為 10。
  2. 宣告另一個名為 isHotval,並將 if/else 陳述式的回傳值指派給 isHot,如下列程式碼所示。由於這是運算式,因此您可以立即使用 if 運算式的值。
val temperature = 10
val isHot = if (temperature > 50) true else false
println(isHot)
⇒ false
  1. 在字串範本中使用運算式的值。新增一些程式碼來檢查溫度,判斷魚是否安全或過熱,然後執行程式。
val temperature = 10
val message = "The water temperature is ${ if (temperature > 50) "too warm" else "OK" }."
println(message)
⇒ The water temperature is OK.

在本工作中,您將進一步瞭解 Kotlin 中的函式,以及非常實用的 when 條件運算式。

步驟 1:建立一些函式

在這個步驟中,您將整合所學內容,並建立不同類型的函式。您可以將 Hello.kt 的內容替換為這段新程式碼。

  1. 編寫名為 feedTheFish() 的函式,呼叫 randomDay() 取得隨機星期幾。使用字串範本,列印當天魚要吃的 food。目前魚每天吃的食物都一樣。
fun feedTheFish() {
    val day = randomDay()
    val food = "pellets"
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}
  1. 編寫 randomDay() 函式,從陣列中隨機挑選一天並傳回。

nextInt() 函式會採用整數限制,將 Random() 中的數字限制為 0 到 6,以符合 week 陣列。

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
            "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}
  1. Random()nextInt() 函式是在 java.util.* 中定義。在檔案頂端新增所需匯入項目:
import java.util.*    // required import
  1. 執行程式,並檢查輸出內容。
⇒ Today is Tuesday and the fish eat pellets

步驟 2:使用 when 運算式

進一步延伸,使用 when 運算式變更程式碼,在不同天選擇不同食物。when 陳述式類似於其他程式設計語言中的 switch,但 when 會在每個分支結尾自動中斷。如果您要檢查列舉,這項功能也會確保程式碼涵蓋所有分支。

  1. Hello.kt 中,新增名為 fishFood() 的函式,該函式會將某天做為 String,並以 String 形式傳回當天的魚食。請使用 when(),確保每天餵魚的食物都不一樣。執行程式幾次,看看不同的輸出內容。
fun fishFood (day : String) : String {
    var food = ""
    when (day) {
        "Monday" -> food = "flakes"
        "Tuesday" -> food = "pellets"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Saturday" -> food = "lettuce"
        "Sunday" -> food = "plankton"
    }
    return food
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)

    println ("Today is $day and the fish eat $food")
}
⇒ Today is Thursday and the fish eat granules
  1. 使用 else 將預設分支版本新增至 when 運算式。如要進行測試,請移除 TuesdaySaturday 分支,確保程式有時會採用預設值。

    預設分支可確保 food 在傳回前取得值,因此不再需要初始化。由於程式碼現在只會將字串指派給 food 一次,因此您可以使用 val (而非 var) 宣告 food
fun fishFood (day : String) : String {
    val food : String
    when (day) {
        "Monday" -> food = "flakes"
        "Wednesday" -> food = "redworms"
        "Thursday" -> food = "granules"
        "Friday" -> food = "mosquitoes"
        "Sunday" -> food = "plankton"
        else -> food = "nothing"
    }
    return food
}
  1. 由於每個運算式都有值,因此您可以讓這段程式碼更簡潔。直接傳回 when 運算式的值,並排除 food 變數。when 運算式的值是滿足條件的分支的最後一個運算式的值。
fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

最終版本的程式碼如下所示。

import java.util.*    // required import

fun randomDay() : String {
    val week = arrayOf ("Monday", "Tuesday", "Wednesday", "Thursday",
        "Friday", "Saturday", "Sunday")
    return week[Random().nextInt(week.size)]
}

fun fishFood (day : String) : String {
    return when (day) {
        "Monday" -> "flakes"
        "Wednesday" -> "redworms"
        "Thursday" -> "granules"
        "Friday" -> "mosquitoes"
        "Sunday" -> "plankton"
        else -> "nothing"
    }
}

fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
}

fun main(args: Array<String>) {
    feedTheFish()
}

在這項工作中,您將瞭解函式和方法的預設值。您也會瞭解精簡函式,這類函式可讓程式碼更簡潔易讀,並減少測試的程式碼路徑數量。緊湊函式也稱為單一運算式函式

步驟 1:為參數建立預設值

在 Kotlin 中,您可以依參數名稱傳遞引數。您也可以為參數指定預設值:如果呼叫端未提供引數,系統就會使用預設值。稍後撰寫方法 (成員函式) 時,您就能避免撰寫大量相同方法的過載版本。

  1. Hello.kt 中,編寫 swim() 函式,並加入名為 speedString 參數,用來列印魚的速度。speed 參數的預設值為 "fast"
fun swim(speed: String = "fast") {
   println("swimming $speed")
}
  1. main() 函式呼叫 swim() 函式,有三種方式。首先,請使用預設值呼叫函式。然後呼叫函式並傳遞不含名稱的 speed 參數,接著呼叫函式並命名 speed 參數。
swim()   // uses default speed
swim("slow")   // positional argument
swim(speed="turtle-like")   // named parameter
⇒ swimming fast
swimming slow
swimming turtle-like

步驟 2:新增必要參數

如果未指定參數的預設值,就必須一律傳遞相應的引數。

  1. Hello.kt 中,編寫 shouldChangeWater() 函式,其中包含三個參數:daytemperaturedirty 層級。如果應該換水 (星期日、水溫過高或水質太髒),函式會傳回 true。必須提供星期幾,但預設溫度為 22,預設髒污程度為 20。

    使用不含引數的 when 運算式,在 Kotlin 中這會做為一系列的 if/else if 檢查。
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        temperature > 30 -> true
        dirty > 30 -> true
        day == "Sunday" ->  true
        else -> false
    }
}
  1. feedTheFish() 呼叫 shouldChangeWater(),並提供日期。day 參數沒有預設值,因此您必須指定引數。shouldChangeWater() 的另外兩個參數都有預設值,因此您不必為這些參數傳遞引數。
fun feedTheFish() {
    val day = randomDay()
    val food = fishFood(day)
    println ("Today is $day and the fish eat $food")
    println("Change water: ${shouldChangeWater(day)}")
}
=> Today is Thursday and the fish eat granules
Change water: false

步驟 3:建立精簡函式

您在上一個步驟中編寫的 when 運算式,會將大量邏輯封裝到少量程式碼中。如果想稍微解壓縮,或是要檢查的條件較為複雜,可以使用一些命名良好的本機變數。但 Kotlin 的做法是使用精簡函式。

緊湊函式或單一運算式函式是 Kotlin 中的常見模式。如果函式傳回單一運算式的結果,您可以在 = 符號後指定函式主體,並省略大括號 {}return

  1. Hello.kt 中,新增小型函式來測試條件。
fun isTooHot(temperature: Int) = temperature > 30

fun isDirty(dirty: Int) = dirty > 30

fun isSunday(day: String) = day == "Sunday"
  1. 變更 shouldChangeWater() 以呼叫新函式。
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20): Boolean {
    return when {
        isTooHot(temperature) -> true
        isDirty(dirty) -> true
        isSunday(day) -> true
        else  -> false
    }
}
  1. 執行程式。使用 shouldChangeWater()println() 輸出內容,應與切換為使用精簡函式前相同。

預設值

參數的預設值不一定要是值,可以是另一個函式,如下列部分範例所示:

fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = getDirtySensorReading()): Boolean {
    ...

在這項工作中,您將稍微瞭解 Kotlin 中的篩選器。篩選器是根據某些條件取得部分清單的實用方法。

步驟 1:建立篩選器

  1. Hello.kt 中,使用 listOf() 在頂層定義水族箱裝飾清單。您可以取代 Hello.kt 的內容。
val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")
  1. 建立新的 main() 函式,並加入一行程式碼,只列印開頭為字母「p」的裝飾。篩選條件的程式碼位於大括號 {} 中,而 it 則是指篩選迴圈中的每個項目。如果運算式傳回 true,就會納入該項目。
fun main() {
    println( decorations.filter {it[0] == 'p'})
}
  1. 執行程式後,您會在「Run」視窗中看到下列輸出內容:
⇒ [pagoda, plastic plant]

步驟 2:比較急切和延遲篩選器

如果您熟悉其他語言的篩選器,可能會想知道 Kotlin 中的篩選器是即時還是延遲。結果清單是立即建立,還是存取清單時才建立?在 Kotlin 中,無論您需要哪種方式,都可以達成。根據預設,filter 為「急切」狀態,每次使用篩選器時都會建立清單。

如要讓篩選器延遲,可以使用 Sequence,這個集合一次只能查看一個項目,從頭開始,然後到結尾。方便的是,這正是延遲篩選器所需的 API。

  1. Hello.kt 中,變更程式碼,將篩選後的清單指派給名為 eager 的變數,然後列印該變數。
fun main() {
    val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

    // eager, creates a new list
    val eager = decorations.filter { it [0] == 'p' }
    println("eager: " + eager)
  1. 在該程式碼下方,使用 SequenceasSequence() 評估篩選器。將序列指派給名為 filtered 的變數,然後列印該變數。
   // lazy, will wait until asked to evaluate
    val filtered = decorations.asSequence().filter { it[0] == 'p' }
    println("filtered: " + filtered)

將篩選結果做為 Sequence 傳回時,filtered 變數不會保留新清單,而是會保留清單元素的 Sequence,以及要套用至這些元素的篩選器知識。每當您存取 Sequence 的元素時,系統就會套用篩選器,並將結果傳回給您。

  1. 將序列轉換為 List (使用 toList()),強制評估序列。列印結果。
    // force evaluation of the lazy list
    val newList = filtered.toList()
    println("new list: " + newList)
  1. 執行程式並觀察輸出內容。
⇒ eager: [pagoda, plastic plant]
filtered: kotlin.sequences.FilteringSequence@386cc1c4
new list: [pagoda, plastic plant]

如要以視覺化方式呈現 Sequence 和延遲求值的情況,請使用 map() 函式。map() 函式會對序列中的每個元素執行簡單的轉換。

  1. 使用與上述相同的 decorations 清單,透過 map() 進行轉換,但不要執行任何動作,只要傳回傳遞的元素即可。新增 println(),在每次存取元素時顯示,並將序列指派給名為 lazyMap 的變數。
    val lazyMap = decorations.asSequence().map {
        println("access: $it")
        it
    }
  1. 列印 lazyMap、使用 first() 列印 lazyMap 的第一個元素,以及列印轉換為 ListlazyMap
    println("lazy: $lazyMap")
    println("-----")
    println("first: ${lazyMap.first()}")
    println("-----")
    println("all: ${lazyMap.toList()}")
  1. 執行程式,看看輸出結果。列印 lazyMap 只會列印 Sequence 的參照,不會呼叫內部 println()。列印第一個元素時,只會存取第一個元素。將 Sequence 轉換為 List 即可存取所有元素。
⇒ lazy: kotlin.sequences.TransformingSequence@5ba23b66
-----
access: rock
first: rock
-----
access: rock
access: pagoda
access: plastic plant
access: alligator
access: flowerpot
all: [rock, pagoda, plastic plant, alligator, flowerpot]
  1. 套用 map 前,請先使用原始篩選器建立新的 Sequence。列印該結果。
    val lazyMap2 = decorations.asSequence().filter {it[0] == 'p'}.map {
        println("access: $it")
        it
    }
    println("-----")
    println("filtered: ${ lazyMap2.toList() }")
  1. 執行程式並觀察額外的輸出內容。與取得第一個元素相同,系統只會針對存取的元素呼叫內部 println()
⇒
-----
access: pagoda
access: plastic plant
filtered: [pagoda, plastic plant]

在這項工作中,您將瞭解 Kotlin 中的 lambda 和高階函式

Lambdas

除了傳統的具名函式,Kotlin 也支援 lambda。Lambda 是用於建立函式的運算式。但這不代表您要宣告已命名函式,而是要宣告沒有名稱的函式。這項功能之所以實用,是因為 lambda 運算式現在可以做為資料傳遞。在其他語言中,lambda 稱為「匿名函式」、「函式常值」或類似名稱。

高階函式

您可以將 lambda 傳遞至其他函式,藉此建立高階函式。在先前的工作中,您建立了名為 filter 的高階函式。您已將下列 lambda 運算式傳遞至 filter,做為要檢查的條件:
{it[0] == 'p'}

同樣地,map 是高階函式,而您傳遞至該函式的 lambda 則是要套用的轉換。

步驟 1:瞭解 Lambda

  1. 如同已命名函式,lambda 也可以有參數。如果是 lambda,參數 (和類型,如有需要) 會位於所謂的函式箭頭 -> 左側。要執行的程式碼會放在函式箭頭的右側。將 lambda 指派給變數後,您就可以像呼叫函式一樣呼叫 lambda。

    使用 REPL (「Tools」>「Kotlin」>「Kotlin REPL」),試試這段程式碼:
var dirtyLevel = 20
val waterFilter = { dirty : Int -> dirty / 2}
println(waterFilter(dirtyLevel))
⇒ 10

在這個範例中,lambda 會採用名為 dirtyInt,並傳回 dirty / 2。(因為過濾可去除髒污)。

  1. Kotlin 的函式類型語法與 lambda 語法密切相關。使用這個語法可清楚宣告保存函式的變數:
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }

程式碼內容如下:

  • 建立名為 waterFilter 的變數。
  • waterFilter 可以是任何函式,該函式會採用 Int 並傳回 Int
  • 將 lambda 指派給 waterFilter
  • lambda 會傳回引數 dirty 除以 2 的值。

請注意,您不必再指定 lambda 引數的型別。系統會透過型別推論計算型別。

步驟 2:建立高階函式

到目前為止,lambda 的範例大多看起來像函式。lambda 的真正強大之處在於用來建立高階函式,其中一個函式的引數是另一個函式。

  1. 編寫高階函式。以下是基本範例,這個函式會採用兩個引數。第一個引數是整數。第二個引數是會接收整數並傳回整數的函式。在 REPL 中試試看。
fun updateDirty(dirty: Int, operation: (Int) -> Int): Int {
   return operation(dirty)
}

程式碼主體會呼叫做為第二個引數傳遞的函式,並將第一個引數一併傳遞給該函式。

  1. 如要呼叫這個函式,請傳遞整數和函式。
val waterFilter: (Int) -> Int = { dirty -> dirty / 2 }
println(updateDirty(30, waterFilter))
⇒ 15

您傳遞的函式不一定要是 lambda,也可以是正規的具名函式。如要將引數指定為一般函式,請使用 :: 運算子。這樣 Kotlin 就會知道您要傳遞函式參照做為引數,而不是嘗試呼叫函式。

  1. 請嘗試將一般具名函式傳遞至 updateDirty()
fun increaseDirty( start: Int ) = start + 1

println(updateDirty(15, ::increaseDirty))
⇒ 16
var dirtyLevel = 19;
dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}
println(dirtyLevel)
⇒ 42
  • 如要在 IntelliJ IDEA 中建立 Kotlin 來源檔案,請先建立 Kotlin 專案。
  • 如要在 IntelliJ IDEA 中編譯及執行程式,請按一下 main() 函式旁邊的綠色三角形。輸出內容會顯示在下方的記錄視窗中。
  • 在 IntelliJ IDEA 中,依序前往「Run」>「Edit Configurations」,指定要傳遞至 main() 函式的命令列引數。
  • Kotlin 中幾乎所有內容都有值。您可以利用這項事實,將 ifwhen 的值做為運算式或傳回值,讓程式碼更加簡潔。
  • 預設引數可讓您不必建立多個版本的函式或方法。例如:
    fun swim(speed: String = "fast") { ... }
  • 精簡函式或單一運算式函式可讓程式碼更易於閱讀。例如:
    fun isTooHot(temperature: Int) = temperature > 30
  • 您已瞭解使用 lambda 運算式的篩選器基本概念。例如:
    val beginsWithP = decorations.filter { it [0] == 'p' }
  • Lambda 運算式是一種運算式,可建立未命名的函式。lambda 運算式定義於大括號 {} 之間。
  • 高階函式中,您會將函式 (例如 lambda 運算式) 做為資料傳遞至其他函式。例如:
    dirtyLevel = updateDirty(dirtyLevel) { dirtyLevel -> dirtyLevel + 23}

本課程內容豐富,如果您是 Lambda 新手,更是如此。後續課程會再次介紹 lambda 和高階函式。

Kotlin 說明文件

如要進一步瞭解本課程的任何主題,或遇到問題,請前往 https://kotlinlang.org

Kotlin 教學課程

https://try.kotlinlang.org 網站提供豐富的教學課程 (稱為 Kotlin Koans)、網頁式解譯器,以及附有範例的完整參考文件。

Udacity 課程

如要查看這個主題的 Udacity 課程,請參閱「程式設計人員的 Kotlin 新手上路課程」。

IntelliJ IDEA

IntelliJ IDEA 的說明文件位於 JetBrains 網站。

本節列出的作業可由課程講師指派給學習本程式碼研究室的學員。講師可自由採取以下行動:

  • 視需要指派作業。
  • 告知學員如何繳交作業。
  • 為作業評分。

講師可以視需求使用全部或部分建議內容,也可以自由指派任何其他合適的作業。

如果您是自行學習本程式碼研究室,不妨利用這些作業驗收學習成果。

回答問題

第 1 題

如果字串 element 包含在呼叫的字串中,contains(element: String) 函式會傳回 true。下列程式碼的輸出內容為何?

val decorations = listOf ("rock", "pagoda", "plastic plant", "alligator", "flowerpot")

println(decorations.filter {it.contains('p')})

[pagoda, plastic, plant]

[pagoda, plastic plant]

[pagoda, plastic plant, flowerpot]

[rock, alligator]

第 2 題

在下列函式定義中,哪一個參數是必要參數?
fun shouldChangeWater (day: String, temperature: Int = 22, dirty: Int = 20, numDecorations: Int = 0): Boolean {...}

numDecorations

dirty

day

temperature

第 3 題

您可以將一般具名函式 (而非呼叫函式的結果) 傳遞至其他函式。你會如何將 increaseDirty( start: Int ) = start + 1 傳遞至 updateDirty(dirty: Int, operation: (Int) -> Int)

updateDirty(15, &increaseDirty())

updateDirty(15, increaseDirty())

updateDirty(15, ("increaseDirty()"))

updateDirty(15, ::increaseDirty)

繼續下一個課程:4. 類別和物件

如要查看課程總覽,包括其他程式碼研究室的連結,請參閱「程式設計人員的 Kotlin 新手上路課程:歡迎參加本課程。