Kotlin學習知識點整理-進階篇-05

Kotlin知識點整理進階

本文是我在學習Kotlin的過程當中整理的一些知識點,若有錯誤,歡迎指正markdown

1、運算符重載

運算符重載使用的是 operator 關鍵字
以加號運算符爲例,實現讓兩個對象相加的功能,語法結構以下:app

class OBj{
    operator fun plus(obj: Obj): Obj{
     //處理相加邏輯
    } 
}
//調用方法以下
val obj1 = Obj()
val obj2 = Obj()
val obj3 = obj1 + obj2 
複製代碼
語法糖表達式和實際調用函數對照表
語法糖表達式 實際調用函數
a + b a.plus(b)
a - b a.minus(b)
a * b a.times(b)
a / b a.div(b)
a % b a.rem(b)
a++ a.inc()
a-- a.dec()
+a a.unaryPlus()
- a a.unaryMinus()
! a a.not()
a == b a.equals(b)
a > b a.compareTo(b)
a < b
a >= b
a <= b
a..b a.rangeTo(b)
a[b] a.get(b)
a[b] = c a.set(b, c)
a in b b.contains(a)

注:最後一個 a in b,表示判斷 a 是否在 b 中,而 b.contains(a) 表示判斷 b 是否包含 a,所以這兩種表達方式是等價的。函數

2、擴展函數 + 運算符重載使用示例

下面來看個示例,如今準備用擴展函數+運算符重載來實現一個讓字符串重複打印指定次數的功能,相似 str * n這種形式,代碼以下:oop

operator fun String.tines(n : Int) : String {
    val builder = StringBuilder()
    repeat(n) {
        builder.append(this)
    }
    return builder.toString
}
複製代碼

operator關鍵字是必不可少的,接着參考上面的表可知函數名是 tines,而後因爲咱們是給字符串添加的擴展函數,故在方法名前面加上了 String ,最後藉助 repeat() 將字符串重複 n 次。post

如今,字符串就有了能夠和數字相乘的能力,好比執行以下代碼:學習

val str = "abc" * 3
println(str)

//最終打印結果就是:abcabcabc
複製代碼

其實 Kotlin 中的 String 類中已經提供了一個 repeat() 函數,因此咱們還能夠簡化上面的函數,以下:ui

operator fun String.tines(n : Int) = repeat(n)
複製代碼

3、高階函數

一、定義高階函數

定義:若是一個函數接收另外一個函數做爲參數,或者返回值的類型是另外一個函數,那麼該函數就稱爲高階函數。this

定義一個函數類型:spa

(String, Int) -> Unit
複製代碼

-> 左邊的部分就是用來聲明該函數接收什麼參數的,多個參數之間使用逗號隔開,若是不接受任何參數,寫一對空括號就能夠。
-> 右邊的部分用於聲明該函數的返回值是什麼類型,若是沒有返回值就使用 Unit,它大體至關於Java中的 voidcode

定義一個高階函數:

fun example(func: (String, Int) -> Unit){
    func("hello",123)
}
複製代碼

用途:高階函數容許讓函數類型的參數來決定函數的執行邏輯。即便是用一個高階函數,只要傳入不一樣的函數類型參數,那麼它的執行邏輯和最終的返回結果就多是徹底不一樣的。
咱們來看一個示例:

fun StringBuilder.build(block: StringBuilder.() -> Unit): StringBuilder{
    block()
    return this
} 
複製代碼

咱們給 StringBuilder 定義了一個擴展函數 build ,它接收一個函數類參數。而且若是在函數類型前面加上了 ClassName. 的語法結構,就表示這個函數類型是定義在哪一個類中的。故這裏的參數加上了 StringBuilder. 的語法結構,就表示這個函數類型是定義在 StringBuilder 這個類中的,這樣的做用是當咱們調用 build 函數時傳入的 Lambda 表達式能夠自動擁有 StringBuilder 的上下文,相似於 apply 函數,不用的地方在於 apply 能夠做用到全部類上,這裏的只能做用在 StringBuilder 類上。
用法以下:

val result = StringBuilder.build{
    append("Start here \n")
    append("str1 str2 \n")
    append("End here")
}
複製代碼

二、內聯函數

內聯函數主要是爲了解決運行Lambda表達式時帶來的運行時開銷。
內聯函數用法 在定義高階函數時加上 inline 關鍵字,以下所示:

inline fun num1AndNum2(num1:Int,num2:Int,operation: (Int,Int) -> Int) : Int{
    val result = operation(num1, num2)
    return result
}
複製代碼

noinline 只想內聯其中一個Lambda表達式:

inline fun num1AndNum2(block1 : () -> Unit, noinline block2 : () -> Unit){
}
複製代碼

Q:爲什麼Kotlin要提供一個 noinline 關鍵字來排除內聯功能?
A:內聯函數的函數類型參數在編譯時會進行代碼替換,所以它沒有真正的參數屬性。非內聯的函數類型參數能夠自由地傳遞給其它任何函數,由於它就是一個真實的參數,而內聯的函數類型參數只容許傳遞給另外一個內聯函數。
(補充:內聯函數與非內聯函數還有一個重要的區別:內聯函數所引用的Lambda表達式中是能夠使用 return 關鍵字來進行函數返回的,而非內聯函數只能局部返回)

上一篇 Kotlin學習知識點整理-進階篇-04

參考資料:
《第一行代碼(第三版)》

相關文章
相關標籤/搜索