【Kotlin】函数类型 ( 函数类型 | 带参数名称的参数列表 | 可空函数类型 | 复杂函数类型 | 带接收者函数类型 | 函数类型别名 | 函数类型实例化 | 函数调用 )
文章目錄
- I . 函數(shù)類型
- II . 帶參數(shù)名的參數(shù)列表
- III . 可空函數(shù)類型
- IV . 復(fù)雜函數(shù)類型解讀
- V . 函數(shù)類型別名
- VI . 帶 接收者類型 的函數(shù)類型
- VII . 函數(shù)類型實(shí)例化
- VIII . 函數(shù)類型自動(dòng)推斷
- IX . 帶接收者的函數(shù)類型 與 不帶接收者的函數(shù)類型 之間的轉(zhuǎn)換
- X . 函數(shù)類型變量調(diào)用
I . 函數(shù)類型
函數(shù)類型格式 : 圓括號(hào)中定義 參數(shù)類型列表 , 使用 -> 由參數(shù)列表指向返回值類型 , 表示接受 參數(shù)類型列表 中的參數(shù) , 返回 返回值類型 的返回值 ;
( 參數(shù)類型列表 ) -> 返回值類型
① 參數(shù)列表 : 參數(shù)類型的列表 , 多個(gè)參數(shù)類型使用逗號(hào)隔開 ;
② -> 符號(hào) : 由參數(shù)列表指向返回值類型 , 該符號(hào)用于分割參數(shù)類型列表 與 返回值類型 ;
③ 返回值類型 : 只有一個(gè)返回值類型 ;
④ 示例 : (Int, Int)->Int 參數(shù)類型 , 表示該參數(shù)傳入兩個(gè) Int 類型的參數(shù) , 返回 Int 類型返回值 ;
II . 帶參數(shù)名的參數(shù)列表
1 . 函數(shù)類型參數(shù)名稱 : 參數(shù)列表中可以只是參數(shù)類型 , 也可以加上參數(shù)的變量名稱 , 參數(shù)名稱可以用于說明參數(shù)的含義 , 增加函數(shù)類型的理解性 ;
2 . 只有參數(shù)類型的函數(shù)類型 : 參數(shù)列表中只有參數(shù)類型 ;
( 參數(shù)類型1 , 參數(shù)類型2 , … 參數(shù)類型n ) -> 返回值類型
3 . 有參數(shù)名稱的函數(shù)類型 : 參數(shù)列表中每個(gè)元素都由 參數(shù)名稱 : 參數(shù)類型 組成 , 多個(gè)列表元素使用逗號(hào)隔開 ;
( 參數(shù)名稱1 : 參數(shù)類型1 , 參數(shù)名稱2 : 參數(shù)類型2 , … 參數(shù)名稱n : 參數(shù)類型n ) -> 返回值類型
4 . 帶參數(shù)名稱的函數(shù)類型示例 :
① 沒有參數(shù)名的函數(shù)類型 : (Int , String)->String ;
② 有參數(shù)名的函數(shù)類型 : (age : Int , name : String)->String ;
III . 可空函數(shù)類型
1 . 函數(shù)類型根據(jù)是否可空分類 : 函數(shù)類型 與 普通變量類型一樣 , 也分為可空類型 , 非空類型 兩類 ;
2 . 默認(rèn)非空類型 : 默認(rèn)的函數(shù)類型都是非空類型 , 即函數(shù)定義時(shí) , 需要對(duì)其進(jìn)行初始化 , 或延遲初始化 ;
3 . 可空類型函數(shù)表示方法 : 可空的函數(shù)類型聲明時(shí) , 需要在函數(shù)類型外部加上括號(hào) , 并在右側(cè)添加 ? 可空符號(hào) ;
( ( 參數(shù)列表 ) -> 返回值類型 ) ?
4 . 可空函數(shù)類型 與 非空函數(shù)類型 示例 :
① 非空函數(shù)類型 : (Int , String)->String , 普通的函數(shù)類型 , 默認(rèn)就是非空的函數(shù)類型 ;
② 可空函數(shù)類型 : ( (Int , String)->String ) ? , 在非空函數(shù)類型基礎(chǔ)上 , 外層添加括號(hào) , 右側(cè)添加 ? , 該函數(shù)類型就變成了可空函數(shù)類型 ;
IV . 復(fù)雜函數(shù)類型解讀
1 . 復(fù)雜函數(shù)類型 :
① 參數(shù)返回值是普通類型 : 如果函數(shù)的參數(shù)類型和返回值類型都是普通的類型還好 , 解讀起來不是很困難 ;
② 參數(shù)返回值是函數(shù)類型 : 如果函數(shù)類型的參數(shù)類型或返回值類型中有函數(shù)類型 , 即嵌套的函數(shù)類型 , 這些函數(shù)類型很復(fù)雜 ;
2 . 右箭頭 -> 符號(hào)的結(jié)合性 : 該符號(hào)是右結(jié)合的 , 解讀時(shí) , 先將第一個(gè) -> 符號(hào)右邊的值理解成返回值 , 再逐步解析 :
( Int , String ) -> ( Float , Double ) -> String
① 分析外層函數(shù)類型 ( 函數(shù)類型 ) : 首先根據(jù)右結(jié)合性 , 從左到右開始解讀 , 讀取到第一個(gè) -> 符號(hào) , 說明這是一個(gè)函數(shù)類型 , ( Int , String ) 是參數(shù)列表 , ( Float , Double ) -> String 是返回值類型 ;
② 分析內(nèi)層函數(shù)類型 ( 外層函數(shù)的返回值類型 ) : 然后繼續(xù)分析 ( Float , Double ) -> String 類型 , 外層的函數(shù)類型的 返回值類型 是一個(gè) 函數(shù)類型 , 該函數(shù)類型參數(shù)列表是 ( Float , Double ) , 返回值是 String 類型 ;
③ 總結(jié) : 這是函數(shù)類型的嵌套 , 外層函數(shù)類型的參數(shù)類型是 ( Int , String ) , 函數(shù)的返回值類型是 ( Float , Double ) -> String 是一個(gè)函數(shù)類型 ;
3 . 最佳實(shí)踐 : 復(fù)雜的函數(shù)類型可讀性很差 , 建議使用圓括號(hào)注明函數(shù)類型的結(jié)合性 , 層次 ;
( Int , String ) -> ( Float , Double ) -> String
這樣表示雖然沒有錯(cuò)誤 , 也能讀懂 , 但是該表示并不是一目了然 , 讀懂理解也要花點(diǎn)時(shí)間 , 完全沒有必要在代碼中出腦筋急轉(zhuǎn)彎題目 , 推薦加上圓括號(hào) , 寫成以下形式 :
( Int , String ) -> ( ( Float , Double ) -> String )
這樣就可以一目了然 , ( Int , String ) 是參數(shù)列表 , ( ( Float , Double ) -> String ) 是返回值類型 , 該返回值類型是一個(gè)函數(shù)類型 ;
不推薦這種反人類的類型定義 , 建議還是以簡潔為主 , 參考 C 語言的函數(shù)類型嵌套 int (*p) (int*, int (*f)(int*)) , C 語言的函數(shù) + 指針類型嵌套 int (*(*p2)[5])(int*) , 這個(gè)需要根據(jù)復(fù)雜指針解讀技巧慢慢解讀 , 要花費(fèi)很長時(shí)間才能搞懂 ;
V . 函數(shù)類型別名
使用 typealias 為函數(shù)類型聲明一個(gè)別名 : 使用函數(shù)類型別名 , 能有效降低代碼的復(fù)雜度 , 提高可讀性 , 函數(shù)類型別名聲明格式如下 :
typealias 別名 = 函數(shù)類型
代碼示例 : 下面的示例中 , 為 (Int, Int) -> Int 函數(shù)類型聲明了一個(gè)別名 , 該別名與函數(shù)類型的作用是一樣的 ;
// 1 . 聲明函數(shù)類型 typealias mathAdd = (Int, Int) -> Int// 2 . 為函數(shù)類型數(shù)理化 var add : mathAdd = {a : Int, b : Int -> a + b}// 3 . 為函數(shù)類型實(shí)例化 var add2 : (Int, Int) -> Int = {a : Int, b : Int -> a + b}fun main() {// 4 . 調(diào)用函數(shù)var result = add(1,2)println("$result")// 5 . 調(diào)用函數(shù)var result2 = add2(1,2)println("$result2") }VI . 帶 接收者類型 的函數(shù)類型
1 . 帶 接收者類型 的函數(shù)類型 : 函數(shù)類型 可以指定 接收者類型 , 格式如下 :
接收者類型.( 參數(shù)類型列表 ) -> 返回值類型
① 接收者類型 : 接收者類型 的含義是 , 這個(gè)接收者類型對(duì)象是 函數(shù)類型 實(shí)例的接收者 , 該對(duì)象擁有該函數(shù) ;
② 上述的 函數(shù)類型 定義 表示 : 接收者類型 對(duì)象 , 調(diào)用 ( 參數(shù)類型列表 ) -> 返回值類型 函數(shù)類型的函數(shù) , 傳入 ( 參數(shù)類型列表 ) 類型的參數(shù) , 將返回 “返回值類型” 的返回值 ;
③ 本質(zhì) : 實(shí)例化該 帶接收者的函數(shù)類型 變量時(shí) , 相當(dāng)于為該接收者類型定義了一個(gè)擴(kuò)展函數(shù) ;
2 . 帶接收者類型的函數(shù)類型示例 :
① 帶接收者類型的函數(shù)類型 : String.(Int, Float)->String ;
② 示例類型解析 : 在 String 類型對(duì)象上 , 調(diào)用 (Int, Int)->String 類型的函數(shù) , 在該函數(shù)中按照順序傳入 Int , Float 兩個(gè)類型的參數(shù) , 那么得到一個(gè) String 類型的返回值 ;
VII . 函數(shù)類型實(shí)例化
函數(shù)類型 變量實(shí)例化 : 給 函數(shù)類型變量 進(jìn)行賦值 , 可以賦值的類型有以下幾種情況 ;
1 . Lambda 表達(dá)式 : 可以將 Lambda 表達(dá)式賦值給函數(shù)類型變量 ;
// 將 Lambda 表達(dá)式賦值給函數(shù)類型變量 var add1 : (Int, Int) -> Int = {a : Int, b : Int -> a + b}2 . 匿名函數(shù) : 匿名函數(shù) 可以直接賦值給 函數(shù)類型 變量 ;
// 將 匿名函數(shù) 賦值給函數(shù)類型變量 var add2 : (Int, Int) -> Int = fun (a : Int, b : Int) : Int {return a + b}3 . 已聲明的函數(shù) : 已經(jīng)聲明的函數(shù) , 可以直接賦值給函數(shù)類型變量 ; 這些函數(shù)可以是 頂層函數(shù) , 成員函數(shù) , 局部函數(shù) , 擴(kuò)展函數(shù) ;
fun add(a : Int, b : Int) : Int {return a + b }// 將頂層的 add 函數(shù)賦值給 add3 函數(shù)類型變量 :: 用于獲取頂層定義的函數(shù) // 如果獲取 類中定義的函數(shù) , 可以使用 類名::函數(shù)名 獲取 var add3 : (Int, Int) -> Int = ::add4 . 函數(shù)變量 : 已經(jīng)聲明的函數(shù)類型屬性 , 可以是頂層屬性 , 成員屬性 , 擴(kuò)展屬性 ;
// 將 Lambda 表達(dá)式賦值給函數(shù)類型變量 var add1 : (Int, Int) -> Int = {a : Int, b : Int -> a + b}// 將已經(jīng)定義好的函數(shù)類型變量重新賦值給 另外一個(gè)函數(shù)類型明亮 var add4 : (Int, Int) -> Int = add15 . 函數(shù)類型 派生類 : 函數(shù)類型可以看做一個(gè)接口 , 類可以實(shí)現(xiàn)該接口 , 在實(shí)現(xiàn)類中實(shí)現(xiàn)具體的函數(shù)操作 , 該 函數(shù)類型接口的實(shí)現(xiàn)類 , 可以賦值給函數(shù)類型變量 ;
class AddOperation : (Int, Int) -> Int{override fun invoke(p1: Int, p2: Int): Int {return p1 + p2} }// 將 函數(shù)類型 接口派生類對(duì)象賦值給 函數(shù)類型變量 var add5 : (Int, Int) -> Int = AddOperation()VIII . 函數(shù)類型自動(dòng)推斷
1 . 變量類型推斷 : Kotlin 中的變量類型可以不用顯示聲明 , 可以根據(jù)其賦值的類型進(jìn)行智能類型推斷 ;
2 . 函數(shù)變量類型推斷 : 函數(shù)類型變量也具有智能類型推斷的性質(zhì) ;
var add = {a : Int, b : Int -> a + b}
上面的代碼中省略了函數(shù)類型變量的函數(shù)類型 , 其賦值的 Lambda 表達(dá)式類型是 (Int, Int) -> Int 類型的 , 因此推斷出 add 變量的函數(shù)類型是 (Int, Int) -> Int 類型的 ;
IX . 帶接收者的函數(shù)類型 與 不帶接收者的函數(shù)類型 之間的轉(zhuǎn)換
帶接收者的函數(shù)類型 , 可以轉(zhuǎn)換為 不帶接收者的函數(shù)類型 , 轉(zhuǎn)換規(guī)則是 , 帶接收者的函數(shù)類型的接收者 , 可以轉(zhuǎn)換為不帶接收者類型的第一個(gè)參數(shù) ;
下面的兩個(gè)函數(shù)類型是等價(jià)的 :
① 自帶接收者的函數(shù)類型 : String.( Int ) -> String
② 不帶接收者的函數(shù)類型 : ( String, Int ) -> String
帶接收者函數(shù)類型 與 不帶接收者函數(shù)類型 轉(zhuǎn)換代碼示例 :
// 字符串 "abc" 調(diào)用該函數(shù) , 傳入 2 參數(shù) , 結(jié)果是 "abcabc" var fun1 : String.( Int ) -> String = {times : Int -> this.repeat(times)}// 這是將 接收者 設(shè)置成了第一個(gè)參數(shù) , 將 String.( Int ) -> String 函數(shù)類型的變量 fun1 賦值給了 // ( String, Int ) -> String 函數(shù)類型變量 var fun2 : ( String, Int ) -> String = fun1fun main() {//"Tom".fun1(2) = TomTomprintln("\"Tom\".fun1(2) = ${"Tom".fun1(2)}")//fun2("Jerry", 2) = JerryJerryprintln("fun2(\"Jerry\", 2) = ${fun2("Jerry", 2)}") }① 自帶接收者的函數(shù)類型 : fun1 是帶接收者的 函數(shù)類型 變量 , 其類型是 String.( Int ) -> String 類型 ;
② 不帶接收者的函數(shù)類型 : fun2 是不帶接收者的 函數(shù)類型變量 , 其類型是 ( String, Int ) -> String 類型 ;
③ 互相賦值 : 將 fun1 變量賦值給 fun2 變量 , 賦值成功 , 說明這兩個(gè)變量類型是相同的 ;
④ 調(diào)用函數(shù) : 分別調(diào)用 fun1 和 fun2 函數(shù) , 調(diào)用結(jié)果相同 ;
執(zhí)行結(jié)果 :
"Tom".fun1(2) = TomTom fun2("Jerry", 2) = JerryJerryX . 函數(shù)類型變量調(diào)用
函數(shù)類型變量調(diào)用 :
① invoke 調(diào)用 : 可以通過 函數(shù)類型變量名.invoke(參數(shù)列表) 調(diào)用該函數(shù) ;
② 直接調(diào)用 : 也可以通過 函數(shù)類型變量名(參數(shù)列表) 直接調(diào)用該函數(shù) , 將該變量名稱當(dāng)做函數(shù)名稱來使用 ;
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的【Kotlin】函数类型 ( 函数类型 | 带参数名称的参数列表 | 可空函数类型 | 复杂函数类型 | 带接收者函数类型 | 函数类型别名 | 函数类型实例化 | 函数调用 )的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Kotlin】Lambda 表达式 (
- 下一篇: 【Android FFMPEG 开发】F