Kotlin 擴展屬性、擴展函數

Kotlin ---- 擴展屬性、擴展函數

在原有類的基礎上,增加功能,及不用改源碼,也不用寫子類!

簡單的示例

擴展屬性
val Float.dpTOpx
    get()= TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,this,
        Resources.getSystem().displayMetrics)

val Float.pxTOdp
get() = this/Resources.getSystem().displayMetrics.density+0.5f
println("轉換結果dpTOpx${200f.dpTOpx}")
println("轉換結果pxTOdp${200f.pxTOdp}")

高級用法 擴展函數

上面的擴展屬性,我們都比較容易上手,但是 擴展函數+函數引用混在一起,很多人就會搞蒙圈了

下面我們就來把它 講清楚:

作用域

其實寫在哪都可以(直接放在頂層目錄下作爲一個 Top-level Function),但是由於不應該給協同開發的同事,造成打擾,我們應該寫在

自己的工作package下 (com.zyg.myTest下)或者某個文件下。

給擴展函數 指定 一個Receiver (接受者)

Receiver 也就是說,指定誰能調用 這個函數。

歸屬問題

在一個類中去寫一個擴展函數


class ExampleTest {
    fun  String.method2(int:Int){
        println(this+int)
    }
	  ...
        "翻滾吧章魚".method2(2020) // print-> "翻滾吧章魚2020"
    }

那麼他就是 ExampleTest 這個類的成員函數,只能在類的內部調用。

引用問題

lambda 中 函數可以通過 ‘’ :: " 雙冒號被指像的 (指像的並不是 函數本身,而是跟函數有相同功能的 ‘對象’ )。

那麼‘擴展函數同樣可以通過“ :: ”被指像 ’ (PS: 但這個方法 需要是 Top-level Function,類的成員函數則不行 )。

示例
fun String.method1(i:Int){
    println("method1${i}")
}
...
(String::method1)("翻滾吧章魚",1) //kotlin 將第一個參數,Receiver調用者傳進去 ; 後面的參數則爲 方法的入參

ps: 可能有同學會問,爲什麼第一個參數要傳 調用者 Receiver 呢?

因爲 我們 拿到的是 函數引用的對象,而不是調用者的對象,我們不可能寫成 「 “翻過滾吧章魚”::method1」對吧。。。

那麼kotlin 提供的途徑就是,在這種調用情況下,增加一個函數參數,並且‘函數調用者’放在第一個參數

這樣我們就可以,用函數引用來調用,成員函數 和 擴展函數了。

引用賦值

可以複製給 兩種 不同的函數變量類型 :有 Receiver 和 無 Receiver 的

val a:String.(Int) -> String = String::method1   // 有
val b:(String,Int) -> String = String::method1   // 無

這兩種類型的 變量也可以相互轉換

val a:String.(Int) -> String = String::method1
val b:(String,Int) -> String = String::method1
val c:(String,Int) ->String = a
val d:String.(Int) ->String = b
A. 等等,既然能相互轉換,是不是說明,無Receiver 的函數引用,也可以賦值給有Receiver 的變量麼?

我有一個大膽的想法:

fun method3(s:String,i:Int):String{
    return s+i
}
...
val e:(String,Int) ->String = ::method3
val f:String.(Int) ->String = ::method3

竟然沒報錯!!!

那這樣的話,我們就可以將一個 普通的函數,使用Receiver 的方式來調用,這個可太爽了吧!

ps:使用的前提的 普通函數的第一個參數類型,要與Receiver 的類型相同。

"翻滾吧章魚".f(101) // 可以調用
"翻滾吧章魚".method3(101) // 這樣會報錯
B.同時反響操作也可以的,但是好像沒什麼用了(有Receiver 的函數引用,也可以賦值給無Receiver 的變量)

總結

本文涉及內容

  • 擴展函數
  • 擴展函數的引用
  • 有無Reveiver 的函數類型的轉換以及 擴展屬性
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章