天天看點

Kotlin 高階函數Kotlin高階函數

文章目錄

  • Kotlin高階函數
    • 函數類型
    • Lambda
      • Java中的Lambda
      • Kotlin中的Lambda
        • 定義
        • 無參數
        • 有參數
        • 匿名函數
    • 帶接收者的函數類型
    • 閉包
    • Kotlin實作接口回調
      • Java思想實作
      • 高階函數思想實作

Kotlin高階函數

函數類型

函數類型(Function Type)指就是函數的類型。

fun add(a: Int, b: Int): Float {
    return (a + b).toFloat()
}

//函數類型為:
(Int, Int) -> Float
           

将函數的參數類型和傳回值類型抽象出來後,就得到函數類型。

(Int, Int) -> Float

表示:參數類型是兩個Int傳回值類型為Float的函數類型。

Lambda

Java中的Lambda

//Java 普通方法
btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(mContext, "hello", Toast.LENGTH_SHORT).show();
    }
});

//Java Lambda
btn.setOnClickListener(v -> Toast.makeText(mContext, "hello", Toast.LENGTH_SHORT).show());
           

Kotlin中的Lambda

定義

{參數名1: 參數類型, 參數名2: 參數類型 -> 函數體}

傳回值為函數體的最後一行代碼
           
//Kotlin 普通方法
btn.setOnClickListener(object : View.OnClickListener {
    override fun onClick(v: View?) {
        Toast.makeText(mContext, "hello", Toast.LENGTH_SHORT).show()
    }
})


//Kotlin Lambda
btn.setOnClickListener({ v: View ->
                        Toast.makeText(mContext, "hello", Toast.LENGTH_SHORT).show()
                       })

//拖尾lambda表達式
//如果Lambda是函數的最後一個參數,可以将Lambda寫在括号外
btn.setOnClickListener() { v: View ->
                          Toast.makeText(this, "1aaa", Toast.LENGTH_SHORT).show()
                         }

//還可以省略小括号
btn.setOnClickListener { v ->
                        Toast.makeText(mContext, "hello", Toast.LENGTH_SHORT).show()
                       }

//如果Lambda是單參,可以省略參數
btn.setOnClickListener {
    Toast.makeText(mContext, "hello", Toast.LENGTH_SHORT).show()
}
           

無參數

fun say() {
    println("sayHello")
}

//簡化為
val say = { println("sayHello") }
           

有參數

fun sum(a: Int, b: Int): Int {
    return a + b
}

//等價于
val sum: (Int, Int) -> Int = { a, b -> a + b }

//等價于
val sum = { a: Int, b: Int -> a + b }
           

lambda表達式可以用調用:

匿名函數

fun sum(a: Int, b: Int): Int {
    return a + b
}

//等價于
val sum = fun(a: Int, b: Int): Int {
    return a + b
}
           

帶接收者的函數類型

格式:A.(B, C) -> D

函數類型加

T.

的文法結構,表示這個函數類型定義在哪個類中,我們在調用lambda的時候會自動擁有

T

的上下文,和

apply

函數的實作方式一樣。

val stringPlus: (a: String, b: String) -> String = { a, b -> a + b }
val intPlus: Int.(Int) -> Int = { b -> this + b }

println(stringPlus.invoke("<-", "->"))
println(stringPlus("Hello, ", "world!"))

println(intPlus.invoke(1, 1))
println(intPlus(1, 2))
println(2.intPlus(3)) // 類擴充調用
           
<-->
Hello, world!
2
3
5
           

閉包

一個函數内部申明或傳回一個函數,那麼這個函數稱為閉包。

在Kotlin中,變量的作用域隻有兩種:全局變量和局部變量。

  • 全局變量:函數内部和函數外部都可以直接通路。
  • 局部變量:隻有在函數内部可以方位。

閉包的設計就是為了能讓開發者在函數外部通路函數内部的局部變量。

fun main() {
    val t = test() //1
    t()//2
    t()//3
}

fun test(): () -> Int {
    var a = 1
    println(a)
    return fun(): Int {
        a++
        println(a)
        return a
    }
}
           

Kotlin實作接口回調

Java思想實作

fun main() {
    val testCallback = TestCallback()
    testCallback.setCallback(object : ICallback {
        override fun onSuccess(msg: String) {
            println("success $msg")
        }

        override fun onFail(msg: String) {
            println("onFail $msg")
        }
    })
    testCallback.init()
}

interface ICallback {
    fun onSuccess(msg: String)
    fun onFail(msg: String)
}

class TestCallback {
    var myCallback: ICallback? = null

    fun setCallback(callback: ICallback) {
        myCallback = callback
    }

    fun init() {
        myCallback?.onSuccess("yes")
    }
}
           

高階函數思想實作

去掉了接口和匿名内部類

fun main() {
    val testCallback = TestCallback()
    testCallback.setCallback({ println("success $it") }, { println("fail $it") })
    testCallback.init()
}

class TestCallback {
    var successCallback: (String) -> Unit? = {}
    var failCallback: (String) -> Unit? = {}

    fun setCallback(successCallback: (String) -> Unit, failCallback: (String) -> Unit) {
        this.successCallback = successCallback
        this.failCallback = failCallback
    }

    fun init() {
        successCallback("yes")
        //failCallback("no")
    }
}