Kotlin擴(kuò)展方法超詳細(xì)介紹
前言
在這一節(jié)為大家繼續(xù)帶來 Kotlin 中的一些高級的內(nèi)容:Kotlin 中的 Kotlin 擴(kuò) 展(Extensions)。
Kotlin 能夠擴(kuò)展一個類的新功能而無需繼承該類。 例如,你可以為一個你不 能修改的來自第三方庫中的類編寫一個新的函數(shù)。 這個新增的函數(shù)就像那個 原始類本來就有的函數(shù)一樣,可以用普通的方法調(diào)用。 這種機(jī)制稱為 擴(kuò)展 函數(shù) 。此外,也有 擴(kuò)展屬性 , 允許你為一個已經(jīng)存在的類添加新的屬 性。想想是不是感覺很瘋狂呢?那接下來就往我們開啟這種瘋狂吧。
一、擴(kuò)展方法
Kotlin 的擴(kuò)展函數(shù)可以讓你作為一個類成員進(jìn)行調(diào)用的函數(shù),但是是定義在這 個類的外部。這樣可以很方便的擴(kuò)展一個已經(jīng)存在的類,為它添加額外的方 法。在 Kotlin 源碼中,有大量的擴(kuò)展函數(shù)來擴(kuò)展 Java,這樣使得 Kotlin 比 Java 更方便使用,效率更高。
1.擴(kuò)展方法的原型

2.擴(kuò)展方法的使用
在 Kotlin 中使用
class Jump {
fun test() {
println("jump test")
//在被擴(kuò)展的類中使用
doubleJump(1f)
}
}
fun Jump.doubleJump(howLong: Float): Boolean {
println("jump:$howLong")
println("jump:$howLong")
return true
}
Jump().doubleJump(2f)
//在被擴(kuò)展類的外部使用
Jump().test()在 Java 中使用
在 Java 中調(diào)用 Kotlin 擴(kuò)展,需要通過擴(kuò)展所在的文件名+.的方式進(jìn)行調(diào)用:
KotlinExtensionKt.doubleJump(new Jump(), 2.0f);
另外,需要注意的是我們需要為這個方法傳遞它被擴(kuò)展類的對象來作為接受者,為什么要傳遞接 受者對象,這是由擴(kuò)展的實現(xiàn)原理所決定的,在原理解析部分會講解。
二、Kotlin擴(kuò)展方法實現(xiàn)原理
在體驗到 Kotlin 擴(kuò)展帶個我們高效編程的同時,我們不禁要問自己幾個問 題:
Kotlin 的擴(kuò)展是怎么實現(xiàn)的?
Kotlin 的擴(kuò)展會不是有性能問題?
接下來我們就從 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 源碼分析,擴(kuò)展函數(shù)的實現(xiàn)非常簡單,它沒有修改接受者類型的成員, 僅僅 是通過靜態(tài)方法來實現(xiàn)的。所以我們不必?fù)?dān)心擴(kuò)展函數(shù)會帶來額外的性能消耗。
三、泛型擴(kuò)展方法
為了考慮到擴(kuò)展函數(shù)的通用型,我們可以借助上面課程中學(xué)習(xí)到的泛型,來 為擴(kuò)展方法進(jìn)行泛型化改造,以 fun MutableList.swap(index1: Int, index2: Int)為例,接下來我們?yōu)樗M(jìn)行泛型化改造:
//泛型化擴(kuò)展函數(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)四、擴(kuò)展屬性
擴(kuò)展屬性提供了一種方法能通過屬性語法進(jìn)行訪問的 API 來擴(kuò)展。盡管它們 被叫做屬性,但是它們不能擁有任何狀態(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}")五、為伴生對象添加擴(kuò)展
如果一個類定義了伴生對象 ,那么我們也可以為伴生對象定義擴(kuò)展函數(shù)與屬性:
class Jump {
companion object {}
}
fun Jump.Companion.print(str: String) {
println(str)
}
Jump.print("伴生對象的擴(kuò)展")就像伴生對象的常規(guī)成員一樣:可以只使用類名作為限定符來調(diào)用伴生對象 的擴(kuò)展成員;
六、Kotlin 中常用的擴(kuò)展
在 Kotlin 的源碼中定義了大量的擴(kuò)展,比如:let,run,apply,了解并運用這些 函數(shù)能幫我們提高編碼效率,接下來就往我們一起揭開這些擴(kuò)展函數(shù)的神秘面紗吧!
let 擴(kuò)展
函數(shù)原型:
fun <T, R> T.let(f: (T) -> R): R = f(this)
let 擴(kuò)展函數(shù)的實際上是一個作用域函數(shù),當(dāng)你需要去定義一個變量在一個特定的作用域范圍內(nèi),那么let 函數(shù)是一個不錯的選擇;let 函數(shù)另一個作用就 是可以避免寫一些判斷 null 的操作。
fun testLet(str: String?) {
//限制 str2 的作用域
str.let {
val str2 = "let 擴(kuò)展"
println(it + str2)
}
// println(str2)//報錯
//避免為 null 的操作
str?.let {
println(it.length)
}
}run 擴(kuò)展
函數(shù)原型:
fun <T, R> T.run(f: T.() -> R): R = f()
run 函數(shù)只接收一個 lambda 函數(shù)為參數(shù),以閉包形式返回,返回值為最后一 行的值或者指定的 return 的表達(dá)式,在 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 擴(kuò)展
函數(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 一般用于一個對象實例初始化的時候,需要對對象中的屬性進(jìn)行賦值。 或者動態(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 擴(kuò)展為控件綁定監(jiān)聽器減少模板代碼
定義擴(kuò)展
//為 Activity 添加 find 擴(kuò)展方法,用于通過資源 id 獲取控件
fun <T : View> Activity.find(@IdRes id: Int): T {
return findViewById(id)
}
//為 Int 添加 onClick 擴(kuò)展方法,用于為資源 id 對應(yīng)的控件添加 onClick 監(jiān)聽
fun Int.onClick(activity: Activity, click: () -> Unit) {
activity.find<View>(this).apply {
setOnClickListener {
click()
}
}
}應(yīng)用擴(kuò)展
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 泛型"
}
}
}在這個案例中我們通過兩個擴(kuò)展方法,大大減少了我們在獲取控件,以及為 控件綁定 onClick 監(jiān)聽時候的模板代碼,而且代碼可讀性更高,更加直觀, 這便是 Kotlin 擴(kuò)展的強(qiáng)大之處。
Kotlin 擴(kuò)展的應(yīng)用案例遠(yuǎn)不止這些,需要大家在下去之后能夠活學(xué)活用,來發(fā) 掘?qū)儆谀阕约旱?Kotlin 擴(kuò)展吧。
到此這篇關(guān)于Kotlin擴(kuò)展方法超詳細(xì)介紹的文章就介紹到這了,更多相關(guān)Kotlin擴(kuò)展內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android?縮放動畫?ScaleAnimation的使用小結(jié)
ScaleAnimation即縮放動畫,應(yīng)用場景特別多,比如常見的隱藏菜單點擊顯示,這篇文章主要介紹了Android?縮放動畫?ScaleAnimation的使用小結(jié),需要的朋友可以參考下2024-03-03
Android懸浮按鈕點擊返回頂部FloatingActionButton
這篇文章主要為大家詳細(xì)介紹了Android懸浮按鈕FloatingActionButton點擊回到頂部的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-02-02
Android 仿高德地圖可拉伸的BottomSheet的示例代碼
這篇文章主要介紹了Android 仿高德地圖可拉伸的BottomSheet的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-07-07
Android使用animator實現(xiàn)fragment的3D翻轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了Android使用animator實現(xiàn)fragment的3D翻轉(zhuǎn)效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-12-12
Android ViewGroup事件分發(fā)和處理源碼分析
這篇文章主要為大家介紹了Android ViewGroup事件分發(fā)和處理源碼分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
android 中win10 使用uwp控件實現(xiàn)進(jìn)度條Marquez效果
這篇文章主要介紹了android 中win10 使用uwp控件實現(xiàn)進(jìn)度條Marquez效果,需要的朋友可以參考下2017-06-06
Android開發(fā)之多媒體文件獲取工具類實例【音頻,視頻,圖片等】
這篇文章主要介紹了Android開發(fā)之多媒體文件獲取工具類,結(jié)合實例形式分析了Android獲取音頻,視頻及圖片等多媒體資源的相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
Android自定義多節(jié)點進(jìn)度條顯示的實現(xiàn)代碼(附源碼)
這篇文章主要介紹了Android自定義多節(jié)點進(jìn)度條顯示的實現(xiàn)代碼,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-03-03

