【Kotlin】扩展函数 ( 扩展函数声明 | 调用方式 | 与成员函数优先级 | 接收者空值处理 )
文章目錄
- I . 擴展函數 總結
- II . 擴展函數概念簡介
- III . 擴展函數簡單示例
- IV . 擴展函數調用選擇方式 : 靜態解析
- V . 擴展函數 調用優先級
- VI . 擴展函數 接收者 空值處理
I . 擴展函數 總結
擴展函數總結 :
① 擴展函數定義方式 : fun 接收者類型.函數名(參數列表){函數體}
② 擴展函數調用方式 : 父類和子類定義了相同函數簽名的擴展函數 , 根據變量聲明的類型調用對應的擴展函數 , 不根據變量的實際類型調用 ;
③ 擴展函數與成員優先級對比 : 成員函數優先級高于擴展函數 , 相同簽名的兩個函數 , 優先調用成員函數 ;
④ 可空接收者類型 : 可以為可空類型的接收者定義擴展函數 , 即聲明擴展函數和調用擴展函數的類型后面都必須有 ? 修飾 ; ( 注意空值判定處理 )
II . 擴展函數概念簡介
1 . 擴展函數聲明格式 : 擴展函數在函數前多了接收者類型 , 函數體中可以使用 this 調用 接收者類型對象中的成員 ;
fun 接收者類型.擴展函數名 ( 擴展函數參數列表 ) {//擴展函數函數體 , 可使用 this 關鍵字調用對象中的成員 }2 . 接收者類型 : 聲明擴展函數時 , 需要指定該函數是為哪個類型擴展的 , 被擴展的類型就是接收者類型 ;
3 . 調用接收者類型對象成員 : 在函數體中使用 this 關鍵字 , 可以調用接收者類型對象中的成員 , 如在下面的示例中 , 在類外部的擴展函數中 , 調用 Student 對象中的 name 成員 , 可以使用 this.name ;
4 . 擴展函數本質 : 為 接收者類型 定義擴展函數 , 并沒有真正的再改類中插入新的成員函數 , 僅能通過 接收這類型對象變量.擴展函數() 的方式來調用這個函數 ;
III . 擴展函數簡單示例
擴展函數代碼示例 :
① 接收者類型擴展 : 為已經定義好的 Student 類 , 定義一個擴展函數 print ;
② 擴展函數參數 : 該擴展函數傳入一個 num : Int 參數 ;
③ this 關鍵字訪問接收者類型對象成員 : 在擴展函數中使用 this 關鍵字訪問 Student 類成員 , this.name 訪問其 name 屬性 , this.age 訪問其 age 屬性 ;
class Student {var name : String = "Tom"var age : Int = 18 }/*為 Student 類定義擴展函數接收者類型 : Student類型名稱 : print參數列表 : num : Intthis 關鍵字 :使用 this 關鍵字可以在擴展函數中訪問對象中的成員 ( 注意可見性 )*/ fun Student.print(num : Int){println("打印學生信息 : 姓名 : ${this.name}, 年齡 : ${this.age}, 學號 : ${num}") }fun main() {//調用 Student 對象的擴展函數var student = Student();//打印學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 1student.print(1) }④ 執行結果 :
打印學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 1IV . 擴展函數調用選擇方式 : 靜態解析
1 . 擴展函數定義 : 為 基類 和 派生類 分別定義相同簽名的擴展函數 , 可以精確控制調用 基類 或 派生類 的擴展函數 ;
2 . 調用方式 : 根據接收者類型確定調用哪個擴展函數 ;
① 接收者類型基類 : 如果 接收者類型 聲明為基類 , 那么就會調用基類的擴展函數 ;
② 這里注意 : 不管其值被賦值成基類對象 , 還是賦值成派生類對象 , 接收者類型被聲明成基類類型 , 調用的擴展函數就是基類的擴展函數 ;
③ 接收者類型派生類 : 如果 接收者類型 聲明為派生類 , 那么就會調用派生類的擴展函數 ;
3 . 代碼示例 :
① 定義父類與子類 : 定義父類 Student , 子類 MaleStudent ;
② 分別為父類 , 子類定義擴展函數 : 為 Student 和 MaleStudent 分別定義 print(num : Int){} 擴展函數 ;
③ 擴展函數調用 : 只要類型聲明成 Student 類型 , 那么其調用的擴展函數就是 Student.print(num : Int){} 擴展函數 , 不管該類型的對象是父類還是子類對象 ; 只要類型聲明成 MaleStudent 類型 , 那么其調用的擴展函數就是 MaleStudent.print(num : Int){} 擴展函數
//定義父類 open class Student {var name : String = "Tom"var age : Int = 18 }//定義子類 class MaleStudent : Student(){ }//父類擴展函數 fun Student.print(num : Int){println("打印學生信息 : 姓名 : ${this.name}, 年齡 : ${this.age}, 學號 : ${num}") }//子類擴展函數 fun MaleStudent.print(num : Int){println("打印男學生信息 : 姓名 : ${this.name}, 年齡 : ${this.age}, 學號 : ${num}") }fun main() {// 1 . 變量聲明為父類類型 , 賦值父類對象//接收者類型聲明為 Student , 但實際對象是 Student 類型的// 此時擴展函數調用 Student 接收類型 的擴展數據var student : Student = Student();//打印學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 1student.print(1)// 2 . 變量聲明為父類類型 , 賦值子類對象//接收者類型聲明為 Student , 但實際對象是 MaleStudent 類型的// 此時擴展函數調用 Student 接收類型 的擴展函數var maleStudent : Student = MaleStudent()//打印學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 2maleStudent.print(2)// 3 . 變量聲明為子類類型 , 賦值子類對象//接收者類型聲明為 MaleStudent , 實際對象是 MaleStudent 類型的// 此時擴展函數調用 MaleStudent 接收類型 的擴展函數var maleStudent2 : MaleStudent = MaleStudent()//打印男學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 3maleStudent2.print(3) }
執行結果 :
打印學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 1 打印學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 2 打印男學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 3V . 擴展函數 調用優先級
1 . 成員函數 優先級高于 擴展函數 : 如果 接收者類型 的擴展函數 與 成員函數有相同的函數簽名 ( 即 函數名 , 參數列表個數 , 類型 , 順序 , 完全相同 ) , 調用該簽名的函數時 , 總是調用成員函數 , 擴展函數永遠無法調用 ;
2 . 擴展函數 成員函數 優先級 代碼示例 :
① 代碼示例 : 接收類型 Student 擴展函數的函數簽名與成員函數都是 print(num : Int) , 成員函數優先級高于擴展函數 , 因此調用該方法簽名的方法時 , 總是調用成員函數 , 擴展函數無法被調用到 ;
open class Student {var name : String = "Tom"var age : Int = 18fun print(num : Int){println("成員函數打印學生信息 : 姓名 : ${this.name}, 年齡 : ${this.age}, 學號 : ${num}")} }//該擴展函數與成員函數簽名相同 , 永遠不會被調用到 fun Student.print(num : Int){println("擴展函數打印學生信息 : 姓名 : ${this.name}, 年齡 : ${this.age}, 學號 : ${num}") }fun main() {var student : Student = Student();//成員函數打印學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 1student.print(1) }② 執行結果 :
成員函數打印學生信息 : 姓名 : Tom, 年齡 : 18, 學號 : 1VI . 擴展函數 接收者 空值處理
1 . 空值處理的兩種類型 :
① 非空類型 : 這是 Kotlin 的默認類型 , 如 Student 類型是非空類型 , 不能被賦值為 null ;
② 可空類型 : 在類型名稱后使用 ? 修飾 , 就是可空類型 , 如 Student? 類型是可空類型 , 該類型可以被賦值成 null ;
2 . 可空接收者類型的擴展函數 :
① 可空類型 : 一般情況下 , 擴展函數的接收者不能為空 , 也可以將接收者類型設置為可空類型 ;
② 擴展函數中判空 : 如果接收者類型可以為空 , 那么盡量在擴展函數中進行判空處理 , 防止出現空值異常 ;
3 . 代碼示例 : 接收者類型是 Student? 類型 , 那么相應的變量類型也要是 Student? 類型 ;
open class Student {var name : String = "Tom"var age : Int = 18 }//可空接收者類型的擴展函數 fun Student?.print(num : Int){if(this == null){println("當前學生對象沒有實例化")}else {println("擴展函數打印學生信息 : 姓名 : ${this.name}, 年齡 : ${this.age}, 學號 : ${num}")} }fun main() {/*默認情況下 變量是非空類型的變量 , 不能被賦值成 null如果變量類型后使用 ? 修飾 , 說明變量可以唄設置為空 , 可以唄賦值 null*/var student : Student? = Student()//必須是 Student? 類型的變量才能被賦值成 null// Student 類型的變量不能被賦值 nullstudent = null//當前學生對象沒有實例化student.print(1) }執行結果 :
當前學生對象沒有實例化總結
以上是生活随笔為你收集整理的【Kotlin】扩展函数 ( 扩展函数声明 | 调用方式 | 与成员函数优先级 | 接收者空值处理 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Kotlin】属性 与 幕后字段 (
- 下一篇: 【Kotlin】扩展属性 ( 扩展变量属