擴(kuò)展不能真正的修改他們所擴(kuò)展的類。通過定義一個(gè)擴(kuò)展,你并沒有在一個(gè)類中插入新成員, 僅僅是可以通過該類型的變量用點(diǎn)表達(dá)式去調(diào)用這個(gè)新函數(shù)。
我們想強(qiáng)調(diào)的是擴(kuò)展函數(shù)是靜態(tài)分發(fā)的,即他們不是根據(jù)接收者類型的虛方法。 這意味著調(diào)用的擴(kuò)展函數(shù)是由函數(shù)調(diào)用所在的表達(dá)式的類型來決定的, 而不是由表達(dá)式運(yùn)行時(shí)求值結(jié)果決定的。
官網(wǎng)上描述如果看的不是特別明白,可以參考下面的例子
open class ExtendTest{
open fun foo2() = "parent_foo2"
}
class ExtendChildTest : ExtendTest(){
override fun foo2() = "child_foo2"
}
fun ExtendTest.foo() = "parent"
fun ExtendChildTest.foo() = "child"
/**
* 拓展是靜態(tài)的。這個(gè)方法下的兩個(gè)顯示,就算調(diào)換位置,效果也是一樣
*/
fun printFoo(param: ExtendTest) {
//這里調(diào)用拓展的時(shí)候,所調(diào)用的對(duì)象是由參數(shù)決定定義時(shí)決定,不是運(yùn)行時(shí)由具體的傳參決定
// 因?yàn)槊鞔_是ExtendTest,不是child類型,
// 所以message的內(nèi)容是parent,不是child,
LogUtils.v(TAG,param.foo())//parent
//下面這個(gè)foo2會(huì)根據(jù)運(yùn)行時(shí)實(shí)際的類型,調(diào)用方法,
//所以這里是child,不是parent
LogUtils.v(TAG,param.foo2())//child
}
fun extendTest(){
printFoo(ExtendChildTest())
}
拓展接收者和拓展分發(fā)者
open class Extend2 {
fun a(){}
}
open class ExtendTest2{
fun test(){}
//Extend是擴(kuò)展接收者,ExtendTest2是擴(kuò)展分發(fā)者
fun Extend2.b(){
toString()//接收者優(yōu)先,這個(gè)是Extend.totring
this@ExtendTest2.toString()
}
}
理解了以上的內(nèi)容在看下官網(wǎng)上最后的例子
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ù)
}
}
class C1 : C() {
override fun D.foo() {
println("D.foo in C1")
}
override fun D1.foo() {
println("D1.foo in C1")
}
}
C().caller(D()) // 輸出 "D.foo in C"
C1().caller(D()) // 輸出 "D.foo in C1" —— 分發(fā)接收者虛擬解析
C().caller(D1()) // 輸出 "D.foo in C" —— 擴(kuò)展接收者靜態(tài)解析
是不是就很清楚了