Kotlin-函數(shù)

函數(shù)聲明

Kotlin 中的函數(shù)使用 fun 關(guān)鍵字聲明:

fun a(): Int {
        return 1
    }
    
    fun aa(x:Int,y:Int):Int{
        return x*y
    }

    fun aaa(x:Int,y:Int)=x*y

    fun b(): String {
        return ""
    }

    fun c():Boolean{
        return true
    }

    fun d(){

    }

    fun e():Unit{

    }

fun aa(a:()-> Unit){
        if (2>3){
            a.invoke()
        }else{
            print("條件不滿足 執(zhí)行不了 \n")
        }
    }

    aa {
        print("條件滿足了 執(zhí)行  \n")
    }


函數(shù)用法

調(diào)用函數(shù)使用傳統(tǒng)的方法:

val result = double(2)

默認(rèn)參數(shù)

函數(shù)參數(shù)可以有默認(rèn)值,當(dāng)省略相應(yīng)的參數(shù)時使用默認(rèn)值。與其他語言相比,這可以減少重載數(shù)量:
給第一個參數(shù)賦默認(rèn)值,第二個參數(shù), 調(diào)用給賦值(age=18),也叫具名參數(shù)

fun main(array:Array<String>){
    getName("李四",age = 12)
    getName(age = 18)
}
fun getName(name:String = "張三",age:Int){
    println("$name,$age")
}

打?。豪钏?12
     張三,18

給最后參數(shù)賦默認(rèn)值,可以簡寫

fun main(array:Array<String>){
   getName(18)
}
fun getName(age:Int,name:String = "張三"){
    println("$age,$name")
}
打印輸出:18,張三

覆蓋方法總是使用與基類型方法相同的默認(rèn)參數(shù)值。 當(dāng)覆蓋一個帶有默認(rèn)參數(shù)值的方法時,必須從簽名中省略默認(rèn)參數(shù)值:

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

class B : A() {
    override fun foo(i: Int) { /*……*/ }  // 不能有默認(rèn)值
}

如果一個默認(rèn)參數(shù)在一個無默認(rèn)值的參數(shù)之前,那么該默認(rèn)值只能通過使用具名參數(shù)調(diào)用該函數(shù)來使用:

fun foo(
    bar: Int = 0, 
    baz: Int,
) { /*……*/ }

foo(baz = 1) // 使用默認(rèn)值 bar = 0

如果在默認(rèn)參數(shù)之后的最后一個參數(shù)是 lambda 表達(dá)式,那么它既可以作為具名參數(shù)在括號內(nèi)傳入,也可以在括號外傳入:

fun foo(
    bar: Int = 0,
    baz: Int = 1,
    qux: () -> Unit,
) { /*……*/ }

foo(1) { println("hello") }     // 使用默認(rèn)值 baz = 1
foo(qux = { println("hello") }) // 使用兩個默認(rèn)值 bar = 0 與 baz = 1
foo { println("hello") }        // 使用兩個默認(rèn)值 bar = 0 與 baz = 1
fun foo(
        bar: Int = 0,
        baz: Int = 1,
        qux: (r: Int,z: Int) -> Unit,
    ) {
        if (bar>baz){
            qux.invoke(bar,baz)
        }
    }

ob.foo(2,1) { r, z ->
        run {
            print(r + z)
        }
    }


具名參數(shù)

fun reformat(
    str: String,
    normalizeCase: Boolean = true,
    upperCaseFirstLetter: Boolean = true,
    divideByCamelHumps: Boolean = false,
    wordSeparator: Char = ' ',
) {
/*……*/
}

// 當(dāng)調(diào)用這個函數(shù)時,你不需要命名它的所有參數(shù):
reformat(
    'String!',
    false,
    upperCaseFirstLetter = false,
    divideByCamelHumps = true,
    '_'
)

// 你可以跳過所有帶有默認(rèn)值的參數(shù):
reformat('This is a long String!')

// 您可以跳過一些帶有默認(rèn)值的參數(shù)。但是,在第一個跳過的參數(shù)之后,必須命名所有隨后的參數(shù):
reformat('This is a short String!', upperCaseFirstLetter = false, wordSeparator = '_')

// 你可以使用spread操作符傳遞一個變量數(shù)目的參數(shù)(vararg):
fun foo(vararg strings: String) { 
        for (s in strings){
            print("s=$s \n")
        }
}
foo(strings = *arrayOf("a", "b", "c"))
// 輸出結(jié)果
a
b
c

對于 JVM 平臺:在調(diào)用 Java 函數(shù)時不能使用具名參數(shù)語法,因為 Java 字節(jié)碼并不總是保留函數(shù)參數(shù)的名稱。


返回 Unit 的函數(shù)

如果一個函數(shù)不返回任何有用的值,它的返回類型是 Unit。Unit 是一種只有一個值——Unit 的類型。這個值不需要顯式返回:

// Unit
fun printHello(name: String?): Unit {
    if (name != null)
        println("Hello $name")
    else
        println("Hi there!")
    // `return Unit` 或者 `return` 是可選的
}

// `return Unit` 或者 `return` 是可選的
fun printHello(name: String?): Unit {
        if (name != null) {
            println("Hello $name")
            return
        } else {
            println("Hi there!")
            return Unit
        }
    }

Unit 返回類型聲明也是可選的。上面的代碼等同于:

fun printHello(name: String?) { …… }

單表達(dá)式函數(shù)

當(dāng)函數(shù)返回單個表達(dá)式時,可以省略花括號并且在 = 符號之后指定代碼體即可:

fun double(x: Int, y: Int): Int {
        return x * y
    }

fun double(x: Int): Int = x * 2

當(dāng)返回值類型可由編譯器推斷時,顯式聲明返回類型是可選的:

fun double(x: Int) = x * 2

顯式返回類型

具有塊代碼體的函數(shù)必須始終顯式指定返回類型,除非他們旨在返回 Unit,在這種情況下它是可選的。 Kotlin 不推斷具有塊代碼體的函數(shù)的返回類型,因為這樣的函數(shù)在代碼體中可能有復(fù)雜的控制流,并且返回類型對于讀者(有時甚至對于編譯器)是不明顯的。


可變數(shù)量的參數(shù)(Varargs)

函數(shù)的參數(shù)(通常是最后一個)可以用 vararg 修飾符標(biāo)記:

fun <T> asList(vararg ts: T): List<T> {
    val result = ArrayList<T>()
    for (t in ts) // ts is an Array
        result.add(t)
    return result
}

允許將可變數(shù)量的參數(shù)傳遞給函數(shù):

val list = asList(1, 2, 3) 

在函數(shù)內(nèi)部,類型 T 的 vararg 參數(shù)的可見方式是作為 T 數(shù)組,即上例中的 ts 變量具有類型 Array <out T>。

只有一個參數(shù)可以標(biāo)注為 vararg。如果 vararg 參數(shù)不是列表中的最后一個參數(shù), 可以使用具名參數(shù)語法傳遞其后的參數(shù)的值,或者,如果參數(shù)具有函數(shù)類型,則通過在括號外部傳一個 lambda。

當(dāng)我們調(diào)用 vararg-函數(shù)時,我們可以一個接一個地傳參,例如 asList(1, 2, 3),或者,如果我們已經(jīng)有一個數(shù)組并希望將其內(nèi)容傳給該函數(shù),我們使用伸展(spread)操作符(在數(shù)組前面加 *):

    // 創(chuàng)建一個數(shù)組
    val a = arrayOf(1, 2, 3)
    // 將數(shù)組 伸展 作為可變參數(shù) 傳入函數(shù)里面處理 --> 返回一個list 
    val list = asList(-1, 0, *a, 4)
    // --> 這個時候 list 里面的元數(shù)是 -1,0,1,2,3,4

可變參數(shù) 函數(shù) 調(diào)用

fun <T> asL(int: Int, vararg s: T, inn: Int): List<T> {
        val result = ArrayList<T>()
        for (t in s) // ts is an Array
            result.add(t)
        return result
    }
    
    val list2 = asL(int=0,"","","",*a,inn = 0)

中綴表示法

標(biāo)有 infix 關(guān)鍵字的函數(shù)也可以使用中綴表示法(忽略該調(diào)用的點與圓括號)調(diào)用。中綴函數(shù)必須滿足以下要求:

infix fun Int.shl(x: Int): Int { …… }

// 用中綴表示法調(diào)用該函數(shù)
1 shl 2

// 等同于這樣
1.shl(2)

函數(shù)作用域

在 Kotlin 中函數(shù)可以在文件頂層聲明,這意味著你不需要像一些語言如 Java、C# 或 Scala 那樣需要創(chuàng)建一個類來保存一個函數(shù)。此外除了頂層函數(shù),Kotlin 中函數(shù)也可以聲明在局部作用域、作為成員函數(shù)以及擴展函數(shù)。

局部函數(shù)

Kotlin 支持局部函數(shù),即一個函數(shù)在另一個函數(shù)內(nèi)部:

fun dfs(graph: Graph) {
    fun dfs(current: Vertex, visited: MutableSet<Vertex>) {
        if (!visited.add(current)) return
        for (v in current.neighbors)
            dfs(v, visited)
    }

    dfs(graph.vertices[0], HashSet())
}

局部函數(shù)可以訪問外部函數(shù)(即閉包)的局部變量,所以在上例中,visited 可以是局部變量:

fun dfs(graph: Graph) {
    val visited = HashSet<Vertex>()
    fun dfs(current: Vertex) {
        if (!visited.add(current)) return
        for (v in current.neighbors)
            dfs(v)
    }

    dfs(graph.vertices[0])
}

成員函數(shù)

成員函數(shù)是在類或?qū)ο髢?nèi)部定義的函數(shù):

class Sample {
    fun foo() { print("Foo") }
}

成員函數(shù)以點表示法調(diào)用:

Sample().foo() // 創(chuàng)建類 Sample 實例并調(diào)用 foo

泛型函數(shù)

函數(shù)可以有泛型參數(shù),通過在函數(shù)名前使用尖括號指定:

fun <T> singletonList(item: T): List<T> { /*……*/ }

內(nèi)聯(lián)函數(shù)

內(nèi)聯(lián)函數(shù)在這里講述。

擴展函數(shù)

擴展函數(shù)在其自有章節(jié)講述。

高階函數(shù)和 Lambda 表達(dá)式

高階函數(shù)和 Lambda 表達(dá)式在其自有章節(jié)講述。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容