初識Kotlin之函數

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

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

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

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中很是常見。this

// 函數做爲參數
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表達式提升了咱們的開發效率。值得咱們去深刻學習。

相關文章
相關標籤/搜索