扩展不能真正的修改他们所扩展的类。通过定义一个扩展,你并没有在一个类中插入新成员, 仅仅是可以通过该类型的变量用点表达式去调用这个新函数。
我们想强调的是扩展函数是静态分发的,即他们不是根据接收者类型的虚方法。 这意味着调用的扩展函数是由函数调用所在的表达式的类型来决定的, 而不是由表达式运行时求值结果决定的。
官网上描述如果看的不是特别明白,可以参考下面的例子
open class ExtendTest{
open fun foo2() = "parent_foo2"
}
class ExtendChildTest : ExtendTest(){
override fun foo2() = "child_foo2"
}
fun ExtendTest.foo() = "parent"
fun ExtendChildTest.foo() = "child"
/**
* 拓展是静态的。这个方法下的两个显示,就算调换位置,效果也是一样
*/
fun printFoo(param: ExtendTest) {
//这里调用拓展的时候,所调用的对象是由参数决定定义时决定,不是运行时由具体的传参决定
// 因为明确是ExtendTest,不是child类型,
// 所以message的内容是parent,不是child,
LogUtils.v(TAG,param.foo())//parent
//下面这个foo2会根据运行时实际的类型,调用方法,
//所以这里是child,不是parent
LogUtils.v(TAG,param.foo2())//child
}
fun extendTest(){
printFoo(ExtendChildTest())
}
拓展接收者和拓展分发者
open class Extend2 {
fun a(){}
}
open class ExtendTest2{
fun test(){}
//Extend是扩展接收者,ExtendTest2是扩展分发者
fun Extend2.b(){
toString()//接收者优先,这个是Extend.totring
this@ExtendTest2.toString()
}
}
理解了以上的内容在看下官网上最后的例子
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() // 调用扩展函数
}
}
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" —— 分发接收者虚拟解析
C().caller(D1()) // 输出 "D.foo in C" —— 扩展接收者静态解析
是不是就很清楚了