Kotlin學習筆記(3)-函數

Andy Lu
8 min readAug 4, 2020

第二期Kotlin讀書會

目錄
1. 什麼是函數?
2. 函數結構剖析
3. 函數作用域
4.呼叫函數
5. 單運算式函數
6. Unit 函數
7. Nothing 類型
8. 函數重載
9. 反引號中的函數名稱

什麼是函數?

函數是能夠完成某項特定任務、可複用的程式碼區塊。程式基本上就是一系列函數的組合,用來完成較複雜的任務。

函數結構剖析

private fun formatHealthStatus(healthPoints: Int, isBlessed: Boolean): String{
return healthStatus
}

其中, private fun formatHealthStatus(healthPoints:Int, isBleesed: Boolean):String 為函數標頭,分為五個部分:

  1. private: 可見性修飾符
  2. fun:函數宣告關鍵字
  3. formatHealthStatus:函數名稱
  4. healthPoints:Int, isBlessed:Boolean:函數參數
  5. String:返回類型

可見性修飾符

函數的可見性預設都是公開的,也就是說,其他所有函數(包括定義於其他檔案中的函數)都能使用。換句話說,只要不明確指定可見性修飾符,函數就是公開的。

Kotlin 的可見性修飾符如下(詳細內容之後會介紹):

  1. public(預設)
  2. private
  3. protected
  4. internal

函數名稱宣告

利用函數宣告關鍵字(fun) 加上函數名稱(Kotlin習慣使用小駝峰樣式命名函數名稱)完成函數名稱宣告。 fun formatHealthStatus()

函數參數

函數參數指定輸入要素(函數利用它們完成任務)的名稱和類型。取決於待處理的任務,函數可能不需要函數,也可能需要幾個甚至更多。

請注意,函式參數是唯獨的,不能在函數本體內再重新設定值。

函數參數可以加上等號給予預設值(Default Value)

如下例:

private fun castFireball(numberFireballs: Int = 2){
println("A glass of Fireball springs into existence. (x$numberFireballs)")
}

返回類型

函數標頭的最後一個元素是返回類型。當函數完成任務後會返回資料,返回類型負責定義返回資料的類型。若沒有返回類型,則表示返回類型為 Unit。

函數本體

函數標題之後,便是定義於大括弧之內的函數本體。這裡是函數執行任務的地方。

函數作用域

private fun formatHealthStatus(healthPoints: Int, isBlessed: Boolean):String{
val healthStatus = when (healthPoints){
...
}
return healthStatus
}

一般把healthStatus變數稱做區域變數,因它只存在於formatHealthStatus函數本體內。或者,換一種說法,healthStatus變數的作用域只侷限於formatHealthStatus函數內。作用域可以理解為變數的生命週期。

當函數結束,區域變數也不存在。

const val MAX_EXPERIENCE: Int = 5000
fun main(){
...
}

上例,MAX_EXPERIENCE變數不在函數或類別內,它是檔案層級變數

在專案範圍內,都能看到或使用者個檔案層級變數(如果有需要,可以加上可見修飾符,修改其可見性)

由於區域變數和檔案層級變數的這種差別,對於這些變數何時需要設定初始值或初始化,編譯器會列出具體的強烈要求。

檔案層級變數在定義時就必須設定值,否則無法編譯程式碼。

區域變數只需要在使用前完成初始化即可。

呼叫函數

fun main() {
val name = "Madrigal"
var healthPoints = 89
val isBlessed = true
...
val healthStatus = formatHealthStatus(healthPoints, isBlessed)
...
}

val healthStatu = formatHealthStatus(healthPoint, isBlessed)這一行程式碼就是函數呼叫,將觸發被呼叫函數去執行定義於函數本體內的動作。

呼叫函數時,必須要在括弧內提供參數要求的輸入資料。這種輸入資料名為引數(arguments),為函數提供輸入資料叫傳入引數

補充:技術上來說,參數(Parameter)是函數需要的東西,而引數是由函數呼叫者傳入,以滿足函數參數的要求。

在呼叫函數的時候,我們也可以使用具名函數引數(Named arguments),如下例:

//不具名函數引數
printPlayerStatus("NONE", true, "Madrigal", status)
//具名函數引數
printPlayerStatus(auraColor = "NONE",
isBlessed = true,
name = "Madrigal",
healthStatus = status)

採用具名函數引數,可以不管引數的順序。反之,不具名函數引數,就得依照函數標頭的定義,嚴格按照順序傳入引數。

具名函數引數的另一個好處,讓程式更清晰直觀。如果一個函數要求多個引數,引數和參數的比對很容易混淆不清,在引數變數名稱和函數參數變數名稱不太一致的時候,更是如此。具名函數引數總是使用參數變數名稱,因此很難搞錯。

單運算式函數(Single-expression functions)

若函數只有一個運算式語句,或者說都只有一行求值語句。Kotlin提供更簡單的方式定義這類函數。以減少若干程式碼。

對於這類單運算式函數,返回類型、大括弧、返回語句都可以省略。
如下例:

fun isValid(inputName: String):Boolean {
return inputName.length
}
//可以改成
fun isValid(inputName: String)= inputName.length

Unit 函數

不是所有函數都有返回值。有些函數是利用副作用(side effect)來執行任務,例如修改某個變數的狀態,或者呼叫其他產生系統輸出的函數等。

在Kotlin中,這類函數叫做 Unit 函數,也就是說它們的返回類型是 Unit 。

void (Java) vs Unit (Kotlin)

void:表示類型資訊不重要,沒有回傳值。

Unit :表示一個函數不返回任何東西,只會返回包含一個值(Unit)的類型 Unit,如此,也能相容於要求和一些類型打交道的泛型函數

Nothing 類型

類似於 UnitNothing類型的函數也不返回任何東西。就編譯器而言, Nothing意味著函數不可能成功執行完成,要麼拋出異常,要麼因某種原因再也回不去函數呼叫者處。

TODO 函數的任務就是拋出異常 — 換句話說,表示永遠別指望它執行成功 — 返回 Nothing類型。

什麼時候會用到 TODO函數呢?有些時候,我們需要先把程式架構描繪出來,這時候函數內可能都還沒有內容,我們就可以填入 TODO,當程式執行到這邊的時候,就會拋出異常,通知我們去實作它。如下例:當執行到這個函數 shouldRetuenAString()時,因為裡面包含了 TODO ,所以會拋出異常。

fun shouldReturnAString():String{
TODO("implement the string building functionality here to return a string")
}

函數重載

一個函數有多種實作方式,稱作具備重載特性。

方法1:預設引述指派

方法2:使用相同的函數名稱定義多種實作。(引數不同)

反引號中的函數名稱

Kotlin有個特別的功能:定義或呼叫以空格和其他特殊字元命名的函數,不過,函數名稱要用一對反引號括起來。

例如:

fun `**~prolly not a good idea!~**`{
...
}
//然後用以下方式呼叫
`**~prolly not a good idea!~**`()

為什麼有此設計呢?

  1. 支援Java互動操作。Kotlin與 Java各自有不同的保留關鍵字,不允許作為函數名稱。透過反引號括住函數名稱,就能避免任何潛在的衝突。

例:Java沒有包含 is 關鍵字,有個方法名稱叫做 is

public static void is(){
...
}

但是,Kotlin中,is 是個保留關鍵字。用反引號後,就能在Kotlin中呼叫Java的is方法。

fun doStuff(){
`is`()
}

2. 在測試檔案中使用更直觀與易懂的函數名稱。

例:

fun `users should be signed out when they click logout`(){}

小結

函數是程式中最常使用的項目之一,Kotlin提供了許多方便的功能,可以簡化我們的程式碼以及提升效率。
下一篇我們將繼續進階探討函數。

謝謝

參考

KotlinLang: Function

Kotlin Programming — The Big Nerd Ranch Guide — Ch4函數

--

--

Andy Lu

Android/Flutter developer, Kotlin Expert, like to learn and share.