11-类中声明扩展
6.2.7 类中声明扩展
Kotlin还允许在一个类的内部为另一个类声明扩展,在这个类扩展中,可能有个多个隐式接收者。所谓隐式接收者,指的是对象成员可以无须通过限定符访问。这当中,扩展声明所在类实例称为分发接收者,而扩展方法的目标类型实例称为扩展接收者。
fun main(args: Array<String>) {
val c: C = C()
val d: D = D()
c.caller(d)
}
class D {
fun bar() { println("D bar") }
}
class C {
fun baz() { println("C baz") }
fun D.foo() {
bar() //调用D.bar
baz() //调用C.baz
}
fun caller(d: D) {
d.foo() //调用扩展函数
}
}
执行上面的代码,输出结果如下。
D bar
C baz
这里在C类中创建了D类的扩展,C被当作分发接收者,而 D则作为扩展接收者。从例子中可以看出,在扩展函数中可以调用分发接收者的成员函数。
如果在调用某一个函数时,出现分发接收者和扩展接收者的成员名字冲突的情况,则以扩展接收者优先。如果要引用分发接收者的成员,我们可以使用this语法。
fun main(args: Array<String>) {
val c: C = C()
val d: D = D()
c.caller(d)
}
class D {
fun bar() { println("D bar") }
}
class C {
fun bar() { println("C bar") } //与D类的bar同名
fun D.foo() {
bar() //调用D.bar(),扩展接收者优先
[email protected]() //调用C.bar()
}
fun caller(d: D) {
d.foo() //调用扩展函数
}
}
以成员形式定义的扩展函数,可以声明为open,而且可以在子类中覆写。这意味着此类函数的分发对于分发接收者类型是虚拟的(virtual),但针对扩展接收者仍然是静态的。
fun main(args: Array<String>) {
C().caller(D()) //输出 "D.foo in C"
C1().caller(D()) //输出 "D.foo in C1" —— 分发接收者虚拟解析
C().caller(D1()) //输出 "D.foo in C" —— 扩展接收者静态解析
}
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")
}
}
执行上面的代码,输出结果如下。
D.foo in C
D.foo in C1
D.foo in C