初識Kotlin之函數


本章通過介紹Kotlin的基本函數,默認參數函數,參數不定長函數,尾遞歸函數,高階函數,Lamdba表達式。來對Kotlin函數做進一步了解。將上一篇的Kotlin變量的知識得以運用。Kotlin變量

Kotlin函數簡介

Kotlin中是通過關鍵字fun聲明函數。和變量一樣,返回值類型放在名稱后面,並用":"冒號分開。Kotlin函數默認修飾符public,且可以在文件頂層聲明。其格式如下

fun 函數名(變量): 返回值類型  {
    
}

Kotlin常見函數

基礎函數

fun getValue(v: Int): Int {
    return v
}

當函數不需要返回任何值時,可以將返回值類型定義成Unit,也可以不顯式返回。

fun setValue(v: Int) {
    
}

參數默認值函數

函數的參數可以有默認值,當函數調用者不給默認參數賦值時,函數體就使用參數的默認值。這樣可以減少很多方法重載的代碼量。

fun setValue(x: Int, y: Int = 10): Int {
    retunr x + y
}
setValue(10) -----> 20
setValue(10, 20) -----> 30

參數默認值函數固然好用。但是由於每個人的編程習慣和編程水平的不同。項目中出現下面的代碼的概率還不低。通過程序打印的結果可以看出,輸出的結果並不是我們預期的21.2,而且10。說明編譯器是調用的是第一個函數。

fun main(args: Array<String>) {
    println(setValue(10)) -----> 10
}
fun setValue(x: Int) = x
fun setValue(x: Int, y: Int = 10, z: Double = 1.2) = x + y + z

還一個語法問題,子類繼承父類的參數默認值函數后,是不允許重寫的函數為其參數指定默認值。好在這種情況編譯器會提示錯誤。

open class FatherClass {
    open fun setValue(x: Int, y: Int = 10, z: Double = 1.2) = x + y + z
}

class SunClass: FatherClass() {
//  An overriding function is not allowed to specify default values for its paramete
    override fun setValue(x: Int, y: Int, z: Double) = x + y + z
}

單表達式函數

若函數體只是單個表達式時,可以省略花括號並用"=" 指定代碼體。了解一下即可,至少遇到了不要驚訝。

fun setValue(x: Int, y: Int) = x + y

不定長參數函數

有很多場景函數的變量的個數是不確定。Java是通過三個點"..."表示不定個數的參數。而Kotlin需要通過關鍵字vararg定義參數,表示函數的參數個數不確定。

fun mathPlus(vararg arguments: Any): Any {
    var result: BigDecimal = BigDecimal.ZERO
    arguments.map {
        result = result.plus(BigDecimal(it.toString()))
    }
    return result
}
mathPlus(1,2,3,4.5) ------> 10.5

尾遞歸函數

Kotlin支持尾遞歸的編程風格。允許一些算法可以通過循環而不是遞歸解決問題,避免堆棧溢出導致的系統不穩定。Kotlin還提供了尾遞歸優化的關鍵字tailrec。但要符合 tailrec 修飾符的條件,需要函數必須將其自身調用作為它執行的最后一個操作。我們用求階乘的代碼演示尾遞歸。

// 尾遞歸,可以保證堆棧不溢出,但是還要考慮數據類型的取值范圍
tailrec fun fibolaAlgorithm(num: Int, result: Int): Int {
    println("剩余遞歸次數 : $num \t 計算結果: $result")
    return if (num == 0) {
        1
    } else {
        fibolaAlgorithm(num - 1, result + num)
    }
}

高階函數

高階函數是Kotlin的一大亮點,高階函數是可以將函數用作參數或返回值的函數。下面代碼中,forEach是函數,println也是一個方法,通過雙冒號將函數作為一個參數傳遞。這種用法在Kotlin中非常常見。

// 函數作為參數
fun paramFun() {
    val list = listOf(1, 2)
    list.forEach(::println)
}
// 函數作為返回值
fun returnFun(): (Int, Int) -> Int {
    return { j, i -> j + i }
}
println(returnFun().invoke(1,2))

閉包函數

閉包就是能夠讀取其他函數內部變量的函數。當我們的程序希望讀取到函數的內部變量,或者希望被訪問的變量保存在內存中。就需要用到閉包。這下這段代碼算是比較典型的閉包函數。

fun closureMethod(i: Int): () -> Int {
    var memoryValue = 1
    return fun(): Int {
        return i + memoryValue++
    }
}
val closure = closureMethod(0)
println(closure()) ------> 1
println(closure()) ------> 2

Kotlin Lamdba表達式

Lambda表達式的本質其實是匿名函數,底層還是通過匿名函數來實現。Lambda的出現確實是減少了代碼量,同時代碼變得更加簡潔明了。

Lamdba語法結構

val/var 變量名: (參數類型,參數類型,...) -> 返回值類型 = { 參數1,參數2,... -> 代碼塊 }

在這個基礎上,Kotlin還支持智能推導模式,讓代碼更簡單,讓讀者更摸不清頭腦,新手看這種代碼一定覺得怪怪的。注意:實參並沒有用括號括起來,而是通過箭頭將實參和代碼塊區分開

//  無參: val/var 變量名: () -> 返回值類型 = { 代碼塊 },
val a:() -> Int = { 10 }

//  有參: val/var 變量名: (變量類型...) -> 返回值類型 = { 參數1,參數2, ... -> 操作參數的代碼 }
val b: (Int, Int) -> Int = {x, y -> x + y }

//  推導: val/var 變量名 = { 參數1: 類型, 參數2: 類型, ... -> 操作參數的代碼 }
val c = { x: Int, y: Int -> x + y }
println(c(1,2)) ------> 3

Lamdba和集合可以擦出愛情的火花,下一章介紹Kotlin集合函數API(filter,map,groupBy,maxBy...)時,你就知道Lamdba有多么強大了。

Kotlin 擴展函數

擴展函數指的是在已有類中添加新的方法,且不會對原類做修改。

fun receiverType.funName(params): returnType{
    /*代碼塊*/
}
  • receiverType:擴展函數的接收者,也就是函數擴展的對象
  • returnType: 擴展函數的返回值類型
  • funName:擴展函數的名稱
  • params:擴展函數的參數,可以為NULL
fun Int.extensionFun(i: Int): Int {
    return this + i
}
println(10.extensionFun(20)) ------> 30

因為擴展函數是可以讓程序員自己添加的,出現函數重名的情況非常常見。所以,如果遇到重名的情況。可以在導入包時,通過 as 關鍵字進行改名。注意:改名后不能再用原來的函數名

import com.kotlin.demo.extensionFun as aliasITDragon
fun main(args: Array<String>) {
    println(1.aliasITDragon(2)) ------> 3
}

如果擴展函數只有一個變量,我們可以使用中綴符號( infix 關鍵字)修飾函數,位於fun關鍵字之前。

infix fun Int.extensionFun(i: Int): Int {
    return this + i
}
println(10 extensionFun 20) ------> 30
println(10.extensionFun(20)) ------> 30

文章到這里就介紹了,Kotlin提供的擴展函數,Lamdba表達式提高了我們的開發效率。值得我們去深入學習。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM