当前位置:嗨网首页>书籍在线阅读

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