Kotlin 知識梳理(2) 函數的定義與調用

1、本文概要

本文是對<<Kotlin in Action>>的學習筆記,若是須要運行相應的代碼能夠訪問在線環境 try.kotlinlang.org,這部分的思惟導圖爲: java

2、在 kotlin 中建立集合

kotlin中,建立HashSetArrayListHashMap的方法以下: 正則表達式

經過打印這些集合的類型,能夠看到是採用的標準的 Java集合類:
這麼作的緣由,是由於使用標準的 Java集合使 kotlin能夠更容易地與 Java代碼交互。當從 Kotlin調用 Java函數的時候,不用轉換它的集合類來匹配 Java的類,反之亦然。

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

運行結果爲:

3、讓函數更好調用

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

運行結果爲:

3.1 命名參數

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

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

下面,咱們使用命名參數,並在不改變函數定義的狀況下,改變傳入參數的順序,也能夠獲得和上面相同的運行結果: 學習

對於命名參數,有如下幾點須要注意:ui

  • 若是在調用一個函數時,指明瞭一個參數的名稱,那它以後的全部參數都要代表名稱。
  • 當調用Java函數時,不能使用命名參數。

3.2 默認參數值

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

運行結果爲:
可是要注意:

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

3.3 頂層函數和屬性

Java中,全部的代碼都須要寫做類的函數,可是在項目中,不少代碼並不能歸屬到類中,這時候咱們通常會定義一個xxUtils類,並在其中聲明static的靜態方法。3d

kotlin中,咱們能夠把這些函數直接放到代碼文件的頂層,不用從屬於任何的類,這些放在文件頂層的函數仍然是包內的成員,若是你須要從包外訪問它,則須要import,但再也不須要額外包一層。code

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、擴展函數和屬性

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

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

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爲屬性的類型。

運行結果爲:

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

5.1 可變參數

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

運行結果爲:
而若是咱們已經將參數打包成一個數組,這時候若是想要將它傳遞給一個接收可變參數的函數,那麼須要先經過 *操做符進行解包:
運行結果爲:

5.2 中綴調用

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

//通常函數調用。
1.to("One")
//中綴調用。
1 to "One"
複製代碼

中綴調用能夠與 只有一個參數的函數 一塊兒使用,不管是普通的函數仍是擴展函數,要容許使用中綴符號調用函數,須要使用infix修飾符來標記它,下面是一個建立Person的函數,咱們採用了擴展函數的方法,這裏的AnyKotlin中全部類的父類,和Java中的Object相同:

運行的結果爲:

6、字符串處理

6.1 分割字符串

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

運行結果爲:

6.2 正則表達式

假設有下面這個字符串

/Users/yole/kotlin-book/chapter.adoc
複製代碼

咱們須要經過這個字符串獲取到chapter.adoc的目錄、文件名和擴展名,若是使用擴展函數,那麼代碼以下:

運行結果爲:
下面是使用正則表達式的作法:
這個正則表達式將一個路徑分爲三個由斜線和點分隔的組:

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

7、局部函數

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

運行的結果爲:


更多文章,歡迎訪問個人 Android 知識梳理系列:

相關文章
相關標籤/搜索