Kotlin 語言學習(2) - 函數的定義與調用

Kotlin 語言學習(1) - Kotlin 基礎

Kotlin 語言學習(2) - 函數的定義與調用

Kotlin 語言學習(3) - 類、對象和接口

Kotlin 語言學習(4) - 數據類、類委託 及 object 關鍵字

Kotlin 語言學習(5) - lambda 表達式和成員引用

Kotlin 語言學習(6) - Kotlin 的可空性

Kotlin 語言學習(7) - Kotlin 的類型系統

Kotlin 語言學習(8) - 運算符重載及其他約定

Kotlin 語言學習(9) - 委託屬性

Kotlin 語言學習(10) - 高階函數:Lambda

Kotlin 語言學習(11) - 內聯函數

Kotlin 語言學習(12) - 泛型類型參數

一、本文概要

二、在 kotlin 中創建集合

kotlin中,創建HashSetArrayListHashMap的方法如下:

通過打印這些集合的類型,可以看到是採用的標準的Java集合類:

這麼做的原因,是因爲使用標準的Java集合使kotlin可以更容易地與Java代碼交互。當從Kotlin調用Java函數的時候,不用轉換它的集合類來匹配Java的類,反之亦然。

在這些集合對象上,我們除了可以使用Java當中定義的基本函數以外,還可以使用kotlin提供的擴展方法,例如下面的lastmax

運行結果爲:

三、讓函數更好調用

下面,我們定義一個函數,它的作用的是打印集合當中的元素,並指定元素之間添加分隔符、前綴和後綴:

運行結果爲:

3.1 命名參數

在上面的例子中,我們指定了分隔符、前綴和後綴三個參數,但是對於這個函數的使用者來說,如果不去看這些函數的聲明,很難看出這些String類型的含義,這時候就可以使用 命名參數 的方法來調用,這有兩點好處:

  • 增加函數的可讀性
  • 以想要的順序指定需要的參數

下面,我們使用命名參數,並在不改變函數定義的情況下,改變傳入參數的順序,也可以得到和上面相同的運行結果:

對於命名參數,有以下幾點需要注意:

  • 如果在調用一個函數時,指明瞭一個參數的名稱,那它之後的所有參數都要表明名稱。
  • 當調用Java函數時,不能使用命名參數

3.2 默認參數值

kotlin中,可以在聲明函數的時候,指定參數的默認值,這樣就可以避免創建重載的函數,例如上面的例子,我們可以在 定義函數 時,指定三個String的默認值,而在 調用函數 的時候,如果沒有傳遞這些參數,那麼將會採用默認值:

運行結果爲:

友情提示:

  • 如果使用常規的調用語法時,必須按照函數聲明中定義的參數順序來給定參數,可以省略的只有排在末尾的參數。
  • 如果使用命名參數,可以省略中間的一些參數,也可以以你想要的任意順序只給定你需要的參數,例如我們只修改前綴和後綴,分隔符仍然採用默認值:

運行結果爲:

3.3 頂層函數和屬性

Java中,所有的代碼都需要寫作類的函數,但是在項目中,很多代碼並不能歸屬到類中,這時候我們一般會定義一個xxUtils類,並在其中聲明static的靜態方法。

kotlin中,我們可以把這些函數直接放到代碼文件的頂層,不用從屬於任何的類,這些放在文件頂層的函數仍然是包內的成員,如果你需要從包外訪問它,則需要import,但不再需要額外包一層。

3.3.1 在 Java 中調用頂層函數

如果我們想要在Java中調用這些頂層函數,則需要通過Kotlin根據包含函數的文件的名稱生成的類,例如我們有兩個文件:

KotlinMethod.kt

fun kotlinFunc() {}

JavaCallKotlin.java:

public class JavaCallKotlin {
    public JavaCallKotlin() {
        KotlinMethodKt.kotlinFunc();
    }
}

前者包含一個頂層函數,那麼在Java中,就會根據該文件名生成一個{文件名}Kt的類型,再通過這個類來調用這個頂層函數。

如果不想使用默認的類名,可以在.kt文件的開頭加上@file:JvmName("類名")的註解。

3.3.2 在 Java 中調用頂層屬性

和函數一樣,屬性也可以放到文件的頂層。默認情況下,頂層屬性和其他任意的屬性一樣,是通過訪問器暴露給Java使用的(如果是val就只有一個getter,如果是var就對應gettersetter)。如果想要把一個常量以public static final的屬性暴露給Java,可以使用const來修飾它。

package com.demo.lizejun.kotlinsample.chapter1

//不可變。
val kotlinVal = "kotlinValue"
//可變。
var kotlinVar = "kotlinVariable"
//常量。
const val kotlinConst = "kotlinConst"
//頂層函數。
fun kotlinFunc() {}

Java中,分別通過以下幾種方式來訪問或者修改這幾個頂層屬性:

package com.demo.lizejun.kotlinsample.chapter3;

import com.demo.lizejun.kotlinsample.chapter1.KotlinMethodKt;

public class JavaCallKotlin {
    public JavaCallKotlin() {
        KotlinMethodKt.kotlinFunc();
        //不可變。
        KotlinMethodKt.getKotlinVal();
        //可變。
        KotlinMethodKt.setKotlinVar("newKotlinVar");
        KotlinMethodKt.getKotlinVar();
        //常量。
        String kotlinConst = KotlinMethodKt.kotlinConst;
    }
}

四、擴展函數和屬性

擴展函數 其實是一個類的成員函數,只不過它定義在類的外面,我們所需要做的,就是在聲明擴展函數的時候,把需要擴展的類或者接口的名稱,放到它的前面,用來調用這個擴展函數的對象,就叫做 接收者對象

在擴展函數中,可以直接訪問被擴展的類的其它方法和屬性,就好像是在這個類自己的方法中訪問它們的一樣,但是擴展函數不允許你打破它的封裝性,擴展函數不能訪問私有的或者是受保護的成員。

4.1 擴展函數的定義和使用

下面我們給String類添加一個擴展函數,返回它的最後一個字符:

運行結果爲:

4.2 在 Java 中使用擴展函數

如果需要在Java中調用擴展函數,那麼把接收者對象作爲第一個參數傳進去即可:

//接收者對象作爲第一個參數。
char lastChar = KotlinMethodKt.last("Kotlin");

4.3 不能重寫的擴展函數

這裏假設我們有兩個類,ViewButton,其中Button繼承於View,我們給這兩個類都添加一個名爲showOff的擴展函數。

運行結果爲:

儘管實際上這個變量是一個Button的對象,但是Kotlin會把擴展函數當做靜態函數來對待,因此 擴展函數不存在重寫

4.4 擴展屬性

擴展屬性提供了一種方法,用來擴展類的API,可以用來訪問屬性,用的是屬性語法而不是函數的語法,儘管他們被稱爲屬性,但它們沒有任何狀態,因爲沒有合適的地方來存儲它們。

現在,我們給StringBuilder添加一個可讀寫的屬性lastChar,用於獲取或者改變它的最後一個字符,包含以下幾點要素:

  • 擴展屬性以var/val關鍵字開頭;
  • 指定擴展屬性的名字、類型;
  • 如果是var那麼提供get()/set(value : T)方法,而如果是val屬性,那麼提供get()方法,其中T爲屬性的類型。

運行結果爲:

五、可變參數、中綴調用和庫的支持

使用關鍵字 vararg,可以用來聲明一個函數將有可能有任意數量的參數,下面例子中,我們定義一個可以接收可變數量Int類型的函數,之後和在Java中一樣,它會被轉換爲[I的整型數組類型:

運行結果爲:

而如果我們已經將參數打包成一個數組,這時候如果想要將它傳遞給一個接收可變參數的函數,那麼需要先通過*操作符進行解包:

運行結果爲:

5.2 中綴調用

中綴調用 不是特殊的內置結構,而是一種特殊的函數調用。在中綴調用中,沒有添加額外的分隔符,函數名稱是直接放在目標對象名稱和參數之間。例如我們聲明瞭一個to函數。

//一般函數調用。
1.to("One")
//中綴調用。
1 to "One"

中綴調用可以與 只有一個參數的函數 一起使用,無論是普通的函數還是擴展函數,要允許使用中綴符號調用函數,需要使用infix修飾符來標記它,下面是一個創建Person的函數,我們採用了擴展函數的方法,這裏的AnyKotlin中所有類的父類,和Java中的Object相同:

運行的結果爲:

六、字符串處理

6.1 分割字符串

Java中,我們會使用split來分割字符串,它接受一個正則表達式作爲參數。但是當我們想分割"."時,會得到一個空的數組,因爲.號表示任何字符的正則表達式。
而在kotlin中,它提供了一個接受Regex類型的重載函數,這樣確保了當有一個字符串傳遞給這些函數的時候,不會被當做正則表達式,我們可以使用擴展函數toRegex將字符串轉換爲正則表達式。

運行結果爲:

6.2 正則表達式

假設有下面這個字符串:

/Users/yole/kotlin-book/chapter.adoc

我們需要通過這個字符串獲取到chapter.adoc的目錄、文件名和擴展名,如果使用擴展函數,那麼代碼如下:

運行結果爲:

下面是使用正則表達式的做法:

這個正則表達式將一個路徑分爲三個由斜線和點分隔的組:

  • .模式從字符串的一開始就進行匹配,所以第一組(.+)包含最後一個斜線之前的子串,這和子串包含所有前面的斜線,因爲它們匹配”任何字符“的模式。
  • 第二組包含最後一個點之前的子串
  • 第三組包含剩餘部分

 

七、局部函數

Java的一個函數當中,有可能存在重複代碼,例如在註冊模塊中,可能需要校驗輸入的多個字段是否有效,那麼校驗的邏輯就可以提取出一個函數,而Kotlin就提供了一種方法:可以在函數中嵌套這些提取的函數,局部函數定義方式和普通函數是相同的。

運行的結果爲:

 see you

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章