Kotlin擴展方法超詳細介紹
前言
在這一節(jié)為大家繼續(xù)帶來 Kotlin 中的一些高級的內(nèi)容:Kotlin 中的 Kotlin 擴 展(Extensions)。
Kotlin 能夠擴展一個類的新功能而無需繼承該類。 例如,你可以為一個你不 能修改的來自第三方庫中的類編寫一個新的函數(shù)。 這個新增的函數(shù)就像那個 原始類本來就有的函數(shù)一樣,可以用普通的方法調(diào)用。 這種機制稱為 擴展 函數(shù) 。此外,也有 擴展屬性 , 允許你為一個已經(jīng)存在的類添加新的屬 性。想想是不是感覺很瘋狂呢?那接下來就往我們開啟這種瘋狂吧。
一、擴展方法
Kotlin 的擴展函數(shù)可以讓你作為一個類成員進行調(diào)用的函數(shù),但是是定義在這 個類的外部。這樣可以很方便的擴展一個已經(jīng)存在的類,為它添加額外的方 法。在 Kotlin 源碼中,有大量的擴展函數(shù)來擴展 Java,這樣使得 Kotlin 比 Java 更方便使用,效率更高。
1.擴展方法的原型
2.擴展方法的使用
在 Kotlin 中使用
class Jump { fun test() { println("jump test") //在被擴展的類中使用 doubleJump(1f) } } fun Jump.doubleJump(howLong: Float): Boolean { println("jump:$howLong") println("jump:$howLong") return true } Jump().doubleJump(2f) //在被擴展類的外部使用 Jump().test()
在 Java 中使用
在 Java 中調(diào)用 Kotlin 擴展,需要通過擴展所在的文件名+.的方式進行調(diào)用:
KotlinExtensionKt.doubleJump(new Jump(), 2.0f);
另外,需要注意的是我們需要為這個方法傳遞它被擴展類的對象來作為接受者,為什么要傳遞接 受者對象,這是由擴展的實現(xiàn)原理所決定的,在原理解析部分會講解。
二、Kotlin擴展方法實現(xiàn)原理
在體驗到 Kotlin 擴展帶個我們高效編程的同時,我們不禁要問自己幾個問 題:
Kotlin 的擴展是怎么實現(xiàn)的?
Kotlin 的擴展會不是有性能問題?
接下來我們就從 Kotlin 反編譯出 Java 代碼上來一探究竟:
fun main() { val test = mutableListOf(1, 2, 3) test.swap(1, 2) println(test) } fun MutableList<Int>.swap(index1: Int, index2: Int) { val tmp = this[index1] this[index1] = this[index2] this[index2] = tmp }
反編譯出 Java 源碼
public final class KotlinExtensionKt { public static final void main() { List test = CollectionsKt.mutableListOf(new Integer[]{1, 2, 3}); swap(test, 1, 2); boolean var1 = false; System.out.println(test); } // $FF: synthetic method public static void main(String[] var0) { main(); } public static final void swap(@NotNull List $this$swap, int index1, int index2) { Intrinsics.checkParameterIsNotNull($this$swap, "$this$swap"); int tmp = ((Number)$this$swap.get(index1)).intValue(); $this$swap.set(index1, $this$swap.get(index2)); $this$swap.set(index2, tmp); } }
從反編譯出的 Java 源碼分析,擴展函數(shù)的實現(xiàn)非常簡單,它沒有修改接受者類型的成員, 僅僅 是通過靜態(tài)方法來實現(xiàn)的。所以我們不必擔(dān)心擴展函數(shù)會帶來額外的性能消耗。
三、泛型擴展方法
為了考慮到擴展函數(shù)的通用型,我們可以借助上面課程中學(xué)習(xí)到的泛型,來 為擴展方法進行泛型化改造,以 fun MutableList.swap(index1: Int, index2: Int)為例,接下來我們?yōu)樗M行泛型化改造:
//泛型化擴展函數(shù) fun <T> MutableList<T>.swap1(index1: Int, index2: Int) { val tmp = this[index1] this[index1] = this[index2] this[index2] = tmp } val test2 = mutableListOf("Android Q", "Android N", "Android M") test2.swap1(0,1) println(test2)
四、擴展屬性
擴展屬性提供了一種方法能通過屬性語法進行訪問的 API 來擴展。盡管它們 被叫做屬性,但是它們不能擁有任何狀態(tài),它不能添加額外的字段到現(xiàn)有的 Java 對象實例。
//為 String 添加一個 lastChar 屬性,用于獲取字符串的最后一個字符 val String.lastChar: Char get() = this.get(this.length - 1) ///為 List 添加一個 last 屬性用于獲取列表的最后一個元素,this 可以省略 val <T>List<T>.last: T get() = get(size - 1) val listString = listOf("Android Q", "Android N", "Android M") println("listString.last${listString.last}")
五、為伴生對象添加擴展
如果一個類定義了伴生對象 ,那么我們也可以為伴生對象定義擴展函數(shù)與屬性:
class Jump { companion object {} } fun Jump.Companion.print(str: String) { println(str) } Jump.print("伴生對象的擴展")
就像伴生對象的常規(guī)成員一樣:可以只使用類名作為限定符來調(diào)用伴生對象 的擴展成員;
六、Kotlin 中常用的擴展
在 Kotlin 的源碼中定義了大量的擴展,比如:let,run,apply,了解并運用這些 函數(shù)能幫我們提高編碼效率,接下來就往我們一起揭開這些擴展函數(shù)的神秘面紗吧!
let 擴展
函數(shù)原型:
fun <T, R> T.let(f: (T) -> R): R = f(this)
let 擴展函數(shù)的實際上是一個作用域函數(shù),當(dāng)你需要去定義一個變量在一個特定的作用域范圍內(nèi),那么let 函數(shù)是一個不錯的選擇;let 函數(shù)另一個作用就 是可以避免寫一些判斷 null 的操作。
fun testLet(str: String?) { //限制 str2 的作用域 str.let { val str2 = "let 擴展" println(it + str2) } // println(str2)//報錯 //避免為 null 的操作 str?.let { println(it.length) } }
run 擴展
函數(shù)原型:
fun <T, R> T.run(f: T.() -> R): R = f()
run 函數(shù)只接收一個 lambda 函數(shù)為參數(shù),以閉包形式返回,返回值為最后一 行的值或者指定的 return 的表達式,在 run 函數(shù)中可以直接訪問實例的公有屬性和方法。
data class Room(val address: String, val price: Float, val size: Float) fun testRun(room: Room) { room.run { println("Room:$address,$price,$size") } }
apply 擴展
函數(shù)原型:
fun <T> T.apply(f: T.() -> Unit): T { f(); return this }
apply 函數(shù)的作用是:調(diào)用某對象的 apply 函數(shù),在函數(shù)范圍內(nèi),可以任意調(diào) 用該對象的任意方法,并返回該對象。
從結(jié)構(gòu)上來看 apply 函數(shù)和 run 函數(shù)很像,唯一不同點就是它們各自返回的 值不一樣,run 函數(shù)是以閉包形式返回最后一行代碼的值,而 apply 函數(shù)的返 回的是傳入對象的本身。
apply 一般用于一個對象實例初始化的時候,需要對對象中的屬性進行賦值。 或者動態(tài) inflate 出一個 XML 的 View 的時候需要給 View 綁定數(shù)據(jù)也會用 到,這種情景非常常見。
fun testApply() { ArrayList<String>().apply { add("testApply") add("testApply") add("testApply") println("$this") }.let { println(it) } }
七、案例
使用 Kotlin 擴展為控件綁定監(jiān)聽器減少模板代碼
定義擴展
//為 Activity 添加 find 擴展方法,用于通過資源 id 獲取控件 fun <T : View> Activity.find(@IdRes id: Int): T { return findViewById(id) } //為 Int 添加 onClick 擴展方法,用于為資源 id 對應(yīng)的控件添加 onClick 監(jiān)聽 fun Int.onClick(activity: Activity, click: () -> Unit) { activity.find<View>(this).apply { setOnClickListener { click() } } }
應(yīng)用擴展
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val textView = find<TextView>(R.id.test) R.id.test.onClick(this) { textView.text = "Kotlin 泛型" } } }
在這個案例中我們通過兩個擴展方法,大大減少了我們在獲取控件,以及為 控件綁定 onClick 監(jiān)聽時候的模板代碼,而且代碼可讀性更高,更加直觀, 這便是 Kotlin 擴展的強大之處。
Kotlin 擴展的應(yīng)用案例遠不止這些,需要大家在下去之后能夠活學(xué)活用,來發(fā) 掘?qū)儆谀阕约旱?Kotlin 擴展吧。
到此這篇關(guān)于Kotlin擴展方法超詳細介紹的文章就介紹到這了,更多相關(guān)Kotlin擴展內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android?縮放動畫?ScaleAnimation的使用小結(jié)
ScaleAnimation即縮放動畫,應(yīng)用場景特別多,比如常見的隱藏菜單點擊顯示,這篇文章主要介紹了Android?縮放動畫?ScaleAnimation的使用小結(jié),需要的朋友可以參考下2024-03-03Android懸浮按鈕點擊返回頂部FloatingActionButton
這篇文章主要為大家詳細介紹了Android懸浮按鈕FloatingActionButton點擊回到頂部的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02Android 仿高德地圖可拉伸的BottomSheet的示例代碼
這篇文章主要介紹了Android 仿高德地圖可拉伸的BottomSheet的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07Android使用animator實現(xiàn)fragment的3D翻轉(zhuǎn)效果
這篇文章主要為大家詳細介紹了Android使用animator實現(xiàn)fragment的3D翻轉(zhuǎn)效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12Android ViewGroup事件分發(fā)和處理源碼分析
這篇文章主要為大家介紹了Android ViewGroup事件分發(fā)和處理源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02android 中win10 使用uwp控件實現(xiàn)進度條Marquez效果
這篇文章主要介紹了android 中win10 使用uwp控件實現(xiàn)進度條Marquez效果,需要的朋友可以參考下2017-06-06Android開發(fā)之多媒體文件獲取工具類實例【音頻,視頻,圖片等】
這篇文章主要介紹了Android開發(fā)之多媒體文件獲取工具類,結(jié)合實例形式分析了Android獲取音頻,視頻及圖片等多媒體資源的相關(guān)操作技巧,需要的朋友可以參考下2017-10-10Android自定義多節(jié)點進度條顯示的實現(xiàn)代碼(附源碼)
這篇文章主要介紹了Android自定義多節(jié)點進度條顯示的實現(xiàn)代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-03-03