Kotlin——初級篇(七):函式基礎總結

Jetictors發表於2018-01-22

Kotlin——初級篇(七):函式基礎總結

對於Kotlin中的函式來說,和JavaScript或者Lua這些語言很像,它有著這些語言的特性。但是也與這些語言就著許多不同之處。或許你更瞭解Java語言,然而對於Java語言來說,它不是不是閉包這個特性的。由於在這篇文章主要是講解函式的基本使用,故而只會講解到函式的定義函式的返回值函式的引數等。剩下的部分我會在這個系列的高階篇會給大家奉上。

目錄

Kotlin——初級篇(七):函式基礎總結

一、函式的宣告及基本使用

Kotlin中函式的宣告,同JavaScript相似。

1.1、函式的宣告

  • Kotlin中的函式宣告關鍵字為:fun
  • 定義格式為:可見性修飾符 fun 函式名(引數名 :型別,...) : 返回值{}

這裡的可見性修飾符請參見我的另一篇文章Kotlin——中級篇(三):可見性修飾符詳解,至於返回值以及引數請繼續往下面看

例:定義一個最基本的函式

fun basis(){
    ...
}
複製程式碼

注意:

  • 上面的例子中沒有可見性修飾符,那是因為Kotlin中預設為public可見性修飾符
  • ()圓括號必須存在,即使是沒有引數的情況下
  • {}大括號必須存在,即使是沒有函式體的時候,不過在Kotlin中有一個特例就是,函式具備返回值的時候,如果只用一個表示式就可以完成這個函式,則可以使用單表示式函式。在下面會詳細的給大家講解
  • 在函式沒有返回值時可以省略其返回值

1.2、成員函式

成員函式是指在物件中的內部函式。你可以參見我的另一篇文章Kotlin——中級篇(一):類(class)詳解

例:宣告一個類,在類中在定義一個方法,這個方法就是這個類的成員函式

class Test{
    fun foo(){}
}
複製程式碼

1.3、函式的使用

函式的使用分為兩種:

  • 普通的使用
  • 成員函式的使用

例:

// 普通的使用
basis()
// 如果函式有返回值
val x = basis()

// 成員函式的使用:先初始化物件,在根據物件使用`中綴符號(.)`呼叫其成員函式
Test().foo()
// 如果函式有返回值
val x = Test().foo()
複製程式碼

二、函式的返回值

Kotlin中,函式的返回值型別可以分為:

  • Unit型別:該型別即無返回值的情況,可以省略。
  • 其他型別: 顯示返回型別的情況

2.1、Unit型別

  • 這個型別可以理解為函式無返回值。

例:

fun unitFun() : Unit{
    println("我是返回值為Unit的函式,Unit可省略")
    return
    
    // return Unit 可省略
    // 或者 return  可省略
}

等價於

 fun unitFun(){
    println("我是返回值為Unit的函式,Unit可省略")
}
複製程式碼

當無返回值時,使用平時Java語法寫普通函式一樣即可。不需顯示寫成Unit。這裡只是做一個介紹而已

2.2 、其他顯示返回型別的返回值

這個型別可以理解為,該函式具有返回值,並且返回值型別不能省略,並且return也不能省略

例: 定義一個返回型別為Int的函式

fun returnFun() : Int{
    return 2
}
複製程式碼

三、函式的引數

對於函式中的引數來說,這裡主要分為幾個模組來講解:

  • 具有引數的基本函式宣告
  • 預設引數,即引數具有預設值
  • 命名引數,當傳遞引數的時候顯示使用引數名 = 引數值
  • 可變數量的引數:即引數的個數不定。

3.1、具有引數的函式定義

定義一個具有引數的函式,使用Pascal表示法定義,即為:name : type。其中的引數必須具有顯示的引數型別,並且引數與引數之間用逗號(,)隔開。

例:

fun funArgs(numA : Int, numB : Float){
    println("numA = $numA \t numB = $numB")
}

fun main(args: Array<String>) {
    funArgs(1,10f)
}
複製程式碼

3.2、預設引數

對於預設引數,即使指一個函式中的引數具有預設值,這樣在使用該函式的時候,可以省略一部分引數,可以減少函式的過載

例:定義個具有預設引數的函式

fun defArgs(numA : Int  = 1, numB : Float = 2f, numC : Boolean = false){
    println("numA  =  $numA \t numB = $numB \t numC = $numC")
}

fun main(args: Array<String>) {
    
    // 預設引數的函式使用
    defArgs()
    defArgs(1,10f,true)
}
複製程式碼

輸出結果為:

numA  =  1 	 numB = 2.0 	 numC = false
numA  =  1 	 numB = 10.0 	 numC = true
複製程式碼

可以看出:當具有預設引數時,可以對是引數有預設值的引數不傳遞引數值。

不過這裡有一點值得注意的是: 當該函式是一個成員函式時,並且該函式時覆寫繼承類中的方法時,則該成員函式必須從簽名中省略該函式的預設值。其實這一點不必過於看重,因為在你覆寫方法時,編輯器都預設會幫你實現的..

舉例說明:

open class A{
    open fun foo(i : Int = 10){}
}

class B : A(){
    override fun foo(i: Int) {
        super.foo(i)
        println(i)
    }
}

fun main(args: Array<String>) {
    B().foo()
}
複製程式碼

輸出結果為:10

如果你對類繼承不瞭解,可以參見我的另一篇文章Kotlin——中級篇(四):繼承類詳解

3.3、命名引數

即在使用函式時顯示使用引數名 = 引數值這種方式傳遞引數

例:這裡舉例一個普通的具有引數函式與具有預設引數函式的結合使用

fun callFun(str : String, 
        isTrue : Boolean = false,
        numA : Int = 2,
        numB: Float = 2.0f,
        numC : Int = 2){}
複製程式碼

可以看出,上面例項中的str引數是不具備預設值的。

  1. 我們可以這樣使用它:

    callFun("str")  // 這樣是可以的,因為後面的引數都具有預設值
    複製程式碼
  2. 當使用非預設引數呼叫它時,使用起來就和Java函式一樣:

    callFun("str",true,2,2.0,2)   // 這樣閱讀性很差,因為你除了看函式的定義外,你不知道這些引數的含義
    複製程式碼
  3. 使用命名引數我們可以使程式碼更具有可讀性:

     callFun("str",isTrue = true,numA = 3, numB = 3.0f, numC = 3)
    複製程式碼
  4. 當我們不需要所有的引數時:

     callFun("str",isTrue = true)
    複製程式碼

不過當我們使用命名引數時,雖然可以提高程式碼的閱讀性,及在我們使用第34時有一個坑,就是Java中不支援這種寫法的。而在實際的專案開發中,幾乎上都是和Java語言混用的。那麼這種用法就不適合了。所有這裡還是推薦使用12兩點的用法。這是隻是介紹Kotlin的這種便利性而已。

3.4、可變數量引數

  • 當一個函式中的引數是不定數量的個數並且是同一個型別,則可是使用vararg修飾符去修飾這個變數,則被vararg修飾的引數相當於一個固定型別的陣列。
  • 宣告格式:fun 函式名(vararg 引數名 : 型別,...) :返回值{}

例:

fun varargFun(numA: Int, vararg str : String){
    // ...
}
複製程式碼

其中,既然vararg修飾的變數相當於一個固定型別的陣列,則我們可以對它進行一些高階的操作。這裡只舉例一些簡單的用法,如果你有興趣,可以參見我的另一篇文章Kotlin——高階篇(五):集合之常用操作符彙總

例:

fun varargFun(numA: Int, vararg str : String){
        // 遍歷
    for (s in str) {
        
    }

// 獲取元素
//    str[index]
//    str.component1() ... str.component5()

// 或者其高階函式用法
//    str.map {  }
//    str.filter {  }
//    str.sortBy {  }

}
複製程式碼

在傳遞引數值時,我們可以一個一個引數的傳遞,或者可以直接傳遞一個當前定義型別的陣列。不過在傳遞陣列時,請使用伸展操作符( * )

例:

普通傳遞 : varargFun(1,"aaa","bbb","ccc","ddd","fff")
陣列傳遞:
        val strArray = arrayOf("aaa","bbb","ccc","ddd","fff")
        varargFun(1,*strArray)
複製程式碼

四、單表示式函式

  • 上面提到了單表示式函式。這裡詳細的講解一下。因為在結構體非常簡單的情況下,使用單表示式函式還是能提高程式碼的閱讀性的,並且可以少些兩行程式碼。
  • 單表示式函式:即函式具備返回值的時候,可以省略花括號並且在=賦值符號之後指定程式碼體,而函式的返回值是有編輯器自動推斷的。

例:

// 無引數的情況
fun test1() = 2                     // 自動推斷為:返回型別為Int

// 有引數的情況
fun test2(num : Int) = num * 2      // 自動推斷為:返回型別為Int

// 或者
fun test3(x : Float, y : Int = 2) = x * y  // 和預設引數一起使用,返回值為Float型

fun main(args: Array<String>) {
    println(test1())
    println(test2(2))
    println(test3(2f))
}
複製程式碼

輸出結果為:

2
4
4.0
複製程式碼

總結

對於Kotlin中函式/方法的基本用法就講解到這裡,在後續的章節中,會為大家奉上函式的高階用法以及高階函式的使用,並且會講到其和lambda表示式的連用。 這一篇講解的內容及其簡單,如果您有程式設計經驗您只要主要關注可變個數引數的函式,以及單表示式函式就可以額。

原始碼

如果各位大佬看了之後感覺還闊以,就請各位大佬隨便star一下,您的關注是我最大的動力。
我的個人部落格Jetictors
GithubJteictors

歡迎各位大佬進群共同研究、探索

QQ群號:497071402

Kotlin——初級篇(七):函式基礎總結

相關文章