首發(fā)于公眾號(hào): DSGtalk1989
8.Kotlin 擴(kuò)展
-
擴(kuò)展函數(shù)
我們可以在任何時(shí)刻,任何地方,去幫類添加擴(kuò)展函數(shù),形式就是如下
fun 擴(kuò)展類.擴(kuò)展方法(){ println("123456") }然后能在任何地方任何時(shí)刻都能使用這個(gè)擴(kuò)展的方法。
如果擴(kuò)展函數(shù)和成員函數(shù)同名,那么優(yōu)先使用成員函數(shù)。
可以擴(kuò)展一個(gè)空的對(duì)象,空的對(duì)象我們使用
Any?去表示fun Any?.newString(): String { if (this == null) return "null" // 空檢測(cè)之后,“this”會(huì)自動(dòng)轉(zhuǎn)換為非空類型,所以下面的 toString() // 解析為 Any 類的成員函數(shù) return toString() }這樣一來我們?cè)谌魏螘r(shí)刻去調(diào)用
toString()方法的話都不會(huì)出現(xiàn)空指針的異常 -
擴(kuò)展屬性
我們還能針對(duì)屬性做擴(kuò)展,比如我們想要為
List類加一個(gè)屬性lastIndex,代表列中的最后一個(gè)值的索引。val <T> List<T>.lastIndex : Int get() = size - 1擴(kuò)展屬性只能用
val來形容,即擴(kuò)展的屬性只能讀取,不能修改。 -
伴生對(duì)象的擴(kuò)展
伴生對(duì)象是我們?cè)趉otlin中一般用來處理單例的方式,可以簡(jiǎn)要的在此做一下說明,我們主要使用
companion關(guān)鍵字來處理//kt文件 class TestInstance{ companion object } //decompile java public final class TestInstance { public static final TestInstance.Companion Companion = new TestInstance.Companion((DefaultConstructorMarker)null); public static final class Companion { private Companion() { } public Companion(DefaultConstructorMarker $constructor_marker) { this(); } } }就是比較經(jīng)典的單例模式,在kotlin中我們可以直接通過
TestInstance.Companion的方式去訪問這個(gè)類的單例,我們可以理解成就是TestInstance.getInstance()方法半生對(duì)象的擴(kuò)展如下:
fun TestInstance.Companion.newFun(a : String) : Int{ val b = a + "1" return b.length } val TestInstance.Companion.property : Int get() = 1 -
擴(kuò)展的作用域
作用域較廣,跨包名調(diào)用也可以直接通過
import的方式直接使用。 -
擴(kuò)展中遇到的各種沖突或同名問題
-
情況1 同名擴(kuò)展函數(shù)
如果出現(xiàn)了同名擴(kuò)展函數(shù),則調(diào)用內(nèi)部函數(shù),不調(diào)用擴(kuò)展函數(shù)
fun D.toString(){ Log.e("extension", "toString") }并沒有用,最終會(huì)調(diào)用類
D自己的toString方法 -
情況2 擴(kuò)展函數(shù)中調(diào)用內(nèi)部同名函數(shù)
擴(kuò)展函數(shù)中出現(xiàn)了擴(kuò)展類中和本類中都有的函數(shù),以擴(kuò)展類中的為主,若想使用本類中的函數(shù),需要加上標(biāo)注
this@ClassNameclass D { fun hello(){} } class C { fun hello(){} fun D.newFun(){ hello() this@C.hello() } }第一個(gè)
hello方法用的是D中的hello,如果想使用C中的hello的話需要加上this@C -
情況3 繼承中出現(xiàn)的擴(kuò)展
首先,我們應(yīng)該很容易理解,如下這種情況,即參數(shù)類型是
D,所以用的應(yīng)該是D的擴(kuò)展函數(shù)foo()open class D { } class D1 : D() { } open class C { open fun D.foo() { println("D.foo in C") } open fun D1.foo() { println("D1.foo in C") } fun caller(d: D) { d.foo() // 調(diào)用擴(kuò)展函數(shù) } }如果
C1繼承了C,同時(shí)復(fù)寫了擴(kuò)展函數(shù),如下:class C1 : C() { override fun D.foo() { println("D.foo in C1") } override fun D1.foo() { println("D1.foo in C1") } }那么調(diào)用
C1的caller方法,無論傳D類型還是D1類型,最終打印的都是println("D.foo in C1")
-
Kotlin學(xué)習(xí)筆記之 1 基礎(chǔ)語法
Kotlin學(xué)習(xí)筆記之 2 基本數(shù)據(jù)類型
Kotlin學(xué)習(xí)筆記之 4 循環(huán)控制
Kotlin學(xué)習(xí)筆記之 5 類和對(duì)象
Kotlin學(xué)習(xí)筆記之 8 擴(kuò)展
Kotlin學(xué)習(xí)筆記之 9 數(shù)據(jù)類與密封類
Kotlin學(xué)習(xí)筆記之 12 對(duì)象表達(dá)式和對(duì)象聲明
Kotlin學(xué)習(xí)筆記之 13 基礎(chǔ)操作符run、with、let、also、apply
Kotlin學(xué)習(xí)筆記之 14 包與導(dǎo)入
Kotlin學(xué)習(xí)筆記之 15 伴生對(duì)象
Kotlin學(xué)習(xí)筆記之 18 函數(shù)
Kotlin學(xué)習(xí)筆記之 19 高階函數(shù)與 lambda 表達(dá)式
Kotlin學(xué)習(xí)筆記之 20 內(nèi)聯(lián)函數(shù)
Kotlin學(xué)習(xí)筆記之 21 解構(gòu)聲明
Kotlin學(xué)習(xí)筆記之 28 協(xié)程基礎(chǔ)
Kotlin學(xué)習(xí)筆記之 29 上下文與調(diào)度器
Kotlin學(xué)習(xí)筆記之 30 協(xié)程取消與超時(shí)
Kotlin學(xué)習(xí)筆記之 31 協(xié)程掛起函數(shù)的組合