擴(kuò)展(extension)是指向已有的類中添加函數(shù)
擴(kuò)展函數(shù)
定義擴(kuò)展函數(shù)時(shí),在函數(shù)前面加上要擴(kuò)展類的名字,以下代碼向MutableList<Int>添加了swap方法
fun MutableList<Int>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // 'this' corresponds to the list
this[index1] = this[index2]
this[index2] = tmp
}
this在extension函數(shù)中指代擴(kuò)展類的實(shí)例
Extensions是靜態(tài)調(diào)用的,也就是說(shuō)調(diào)用哪個(gè)類的extension函數(shù)是在編譯時(shí)決定的,而不是動(dòng)態(tài)運(yùn)行時(shí)調(diào)用的
open class C
class D: C()
fun C.foo() = "c"
fun D.foo() = "d"
fun printFoo(c: C) {
println(c.foo()) \\ "c"
}
printFoo(D())
如果extension函數(shù)和成員函數(shù)沖突,那么會(huì)調(diào)用成員函數(shù)
extension函數(shù)可以overload成員函數(shù)
擴(kuò)展類可以是null
fun Any?.toString(): String {
if (this == null) return "null"
// after the null check, 'this' is autocast to a non-null type, so the toString() below
// resolves to the member function of the Any class
return toString()
}
擴(kuò)展屬性
val <T> List<T>.lastIndex: Int
get() = size - 1
擴(kuò)展屬性不能初始化,只能定義getter和setter方法
Companion Object
可以對(duì)Companion Object定義擴(kuò)展函數(shù)和擴(kuò)展屬性
在函數(shù)內(nèi)部定義擴(kuò)展
class D {
fun bar() { ... }
}
class C {
fun baz() { ... }
fun D.foo() {
bar() // calls D.bar
baz() // calls C.baz
}
fun caller(d: D) {
d.foo() // call the extension function
}
}
如果擴(kuò)展類和定義類的函數(shù)名沖突,會(huì)優(yōu)先使用擴(kuò)展類的函數(shù),如果要使用定義類的函數(shù),需要使用qualified this
class C {
fun D.foo() {
toString() // calls D.toString()
this@C.toString() // calls C.toString()
}
擴(kuò)展還可以用open修飾,在子類中可以override
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() // call the extension function
}
}
class C1 : C() {
override fun D.foo() {
println("D.foo in C1")
}
override fun D1.foo() {
println("D1.foo in C1")
}
}