函數和Lambda表達式(一)

函數入門

函數的定義和調用

函數的定義語法如下:

fun 函數名(形參列表):返回值類型{
//函數體
}

kotlin聲明函數必須使用fun關鍵字

函數的返回值可以是kotlin所允許的任何數據類型,如何聲明瞭函數的返回值類型,則函數體必須有一條有效的return語句,該語句返回了一個變量或者表達式,如果沒有返回值則有如下2種聲明方式:

  1. 省略“:返回值類型”部分
  2. 使用“:Unit”指定返回Unit代表沒有返回值,相當於java中的void

函數的形參列表用於定義該函數可以接受的參數,形參列表由多組“形參名:形參類型”組合而成,中間以逗號隔開。


fun max(x: Int, y: Int): Int {
    val z = if (x > y) x else y
    return z
}

fun sayHi(name: String): String {
    return "${name} ,你好!"
}

fun foo() {
    println("執行foo()函數")
}

fun sayHello(name: String): Unit {
    print("${name},hello!")

}

fun main(args: Array<String>) {
    var a = 6
    var b = 9
    println("最大值是: ${max(a, b)}")

    print(sayHi("xq"))

    foo()

    sayHello("sq")
}

遞歸函數

在一個函數體內調用它自身,被稱爲函數的遞歸。

//遞歸函數
fun fn(n: Int): Int {
    when (n) {
        0 -> return 1
        1 -> return 4
        else -> return 2 * fn(n - 1) + fn(n - 2)
    }
}

fun main(args: Array<String>) {

    println("fn(10)的結果是${fn(10)}")

}

單表達式函數

在某些情況下,函數只返回單個表達式,此時可以省略花括號並在等號後指定函數體即可,這種方式被稱爲單表達式函數。對於單表達式函數而言,編譯器可以推導出函數的返回值類型,因此可以省略不寫。


//單表達式函數
fun area(x: Double, y: Double): Double = x + y

fun product(x: Double, y: Double) = x * y

fun main(args: Array<String>) {

    println("1.2 + 2.5 = ${area(1.2, 2.5)}")
    println("1.2 * 2.5 = ${product(1.2, 2.5)}")
}

函數的形參

命名參數

kotlin函數的參數名不是無意義的,kotlin允許調用函數時通過名字來傳入參數值。
注意在調用函數時混合使用命名參數和位置參數時,那麼命名參數必須位於位置參數的後面。


//函數的形參
//命名函數
fun girth(width: Double, height: Double): Double {
    println("width: ${width},height: ${height}")
    return 2 * (width + height)
}
fun main(args: Array<String>) {
    //傳統調用函數的方式,根據位置傳入參數
    girth(3.5, 4.9)
    //根據參數名來傳入參數
    girth(width = 3.5, height = 4.9)
    //使用命名參數是可交換位置
    girth(height = 4.9, width = 3.5)
    //部分使用命名參數,部分使用位置參數  混合使用時命名參數必須位於位置參數之後
    girth(3.5, height = 4.9)
}

形參默認值

在某些情況下,程序需要在定義函數時爲一個或多個形參指定默認值,這樣調用函數時就可以省略該形參,而直接使用默認值。爲形參指定默認值的語法如下:

形參名: 形參類型 = 默認值

如果在定義函數時將有默認值的參數放在了普通參數的前面,並且不想爲默認參數重新傳入參數值,那麼就只能使用命名參數爲其他參數傳入參數值。所以不建議這種寫法。


//形參默認值
fun sayHi(name: String = "xq", msg: String = "welcome") {
    println("name: $name ,msg: $msg")
}

fun printTriangle(height: Int = 5, char: Char) {
    for (i in 1..height) {
        for (j in 0 until height - 1) {
            print(" ")
        }

        for (j in 0 until 2 * i - 1) {
            print(char)
        }
        println()
    }

}
fun main(args: Array<String>) {
    //全部使用默認值
    sayHi()
    //只有msg使用默認值
    sayHi("xy")
    //2個都不使用默認值
    sayHi("sqq", "hi")
    //只有name使用默認值
    sayHi(msg = "你好")

    printTriangle(6, '@')
    printTriangle(7, char = '#')
    printTriangle(char = '*')
}

尾遞歸函數

kotlin還支持一種尾遞歸函數的編程方式,當函數將調用自身作爲它執行的最後一行代碼,且遞歸調用之後沒有更多代碼時,可以使用尾遞歸語法。另外尾遞歸不能再異常處理的try,catch,finally中使用,尾遞歸需要使用tailrec修飾。


//尾遞歸函數
fun fact(n: Int): Int {
    return when (n) {
        1 -> 1
        else -> n * fact(n - 1)
    }
}
tailrec fun factRec(n: Int, total: Int = 1): Int =
//if (n == 1) total else factRec(n - 1, total * n)
        when (n) {
            1 -> total
            else -> factRec(n - 1, total * n)
        }

fun main(args: Array<String>) {
    println("fact(10): ${fact(10)}")
    println("factRec(10):${factRec(10)}")
}

個數可變的形參

kotlin允許定義個數可變的參數,從而爲函數指定數量不確定的形參,如果在定義函數時,在形參的類型前面添加了vararg修飾,則表明該形參可以接受多個參數值,多個參數值被當做數組傳入。

kotlin允許個數可變的形參處於形參列表的任何位置,但是要求一個函數最多只能有一個個數可變的形參,如果個數可變的形參位於參數列表的第一個,因此如果給後面參數賦值時必須使用命名參數。


//個數可變的形參
fun test(a: Int, vararg books: String) {
    for (b in books) {
        println(b)
    }
    println(a)
}
fun main(args: Array<String>) {
    test(2, "java", "kotlin")
}

函數重載

kotlin允許定義多個同名函數,只要它們的形參列表或者返回值類型不同就行。如果程序包含了2個或者以上函數名相同,但是僅有參數列表不同的函數,就被成爲函數重載。


fun test(a: Int, vararg books: String) {
    for (b in books) {
        println(b)
    }
    println(a)
}

//函數的重載
fun test() {
    println("函數的重載,上面是有參的函數")
}

fun main(args: Array<String>) {
    test(2, "java", "kotlin")
    test()
}

局部函數

之前我們所看到的函數都是在全局範圍內定義的,它們都是全局函數,kotlin還支持在函數體內部定義函數,這種函數稱爲局部函數。

在默認的情況下,局部函數都是對外部隱藏的,局部函數只能在其封閉的函數體內有效,其封閉函數也可以返回局部函數,以便程序在其他作用域中使用局部函數。


//局部函數
fun mathFunc(type: String, nn: Int): Int {
    fun square(n: Int): Int {
        return n * n
    }

    fun cube(n: Int): Int {
        return n * n * n
    }

    when (type) {
        "square" -> return square(nn)
        "cube" -> return cube(nn)
        else -> return 0
    }
}



fun main(args: Array<String>) {
    println(mathFunc("square", 3))
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章