【Kotlin】扩展接收者 与 分发接收者 ( 类内部扩展用法 | 注意事项 | open 修饰扩展 )

举报
韩曙亮 发表于 2022/01/11 02:24:24 2022/01/11
【摘要】 文章目录 I . 类内部扩展其它类II . 扩展接收者 与 分发接收者 注意事项III . open 修饰 分发接收者 类型中的扩展 I . 类内部扩展其它类 ...



I . 类内部扩展其它类



1 . 扩展函数 / 属性声明的位置 : 之前的扩展都是在类的外部 , Kotlin 文件中定义的 , 类内部 也可以定义 其它类 的扩展函数 与 扩展属性 ;


2 . 类内部定扩展 : 在这样的扩展函数或扩展属性访问器中 , 可以直接调用本类的成员 ; 类内部扩展其它类 , 也相应产生了两个概念 , 扩展接收者 和 分发接收者 ;


① 扩展接收者 : 被扩展的接收者类型的类对象实例 , 叫做扩展接收者 ;

② 分发接收者 : 扩展函数/属性所在的实例 , 叫做分发接收者 ;


注意 : 扩展接收者 和 分发接收者 都是类的 对象实例 ;


③ 分发接收者中的扩展 : 扩展中可以访问 分发接收者 和 扩展接收者 , 两个实例对象的成员 ;


3 . 扩展接收者 和 分发接收者 代码示例 :

//扩展接收者类型 , 为该类扩展函数
class Teacher{
    var name : String = "Jerry"
}

//分发接收者类型 , 在该类中为 Teacher 扩展函数
class Student{
    var name : String = "Tom"

    // Student 类中的方法
    fun study(){
        println("${name} 在学习")
    }

    /*
        在 Student 类中为 Teacher 类定义扩展函数

        扩展函数内部可以调用 Teacher 和 Student 两个对象的成员
     */
    fun Teacher.teach(){
        //调用 扩展接收者 的 name 属性
        println("${this.name} 在讲课")

        //调用 分发接收者 的 name 属性
        println("${this@Student.name} 在听课")
    }

    //类内部扩展的函数 , 只能在 分发接收者 对象中调用 , 不能在类外部调用
    fun teachAndStudy(){
        Teacher().teach()
    }
}

fun main() {
    Student().teachAndStudy()

    //在分发接收者类型中定义的扩展 ,
    // 只能在该类内部调用 , 在类外部是访问不到的
    //Teacher().teach()
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

执行结果 :

Jerry 在讲课
Tom 在听课

  
 
  • 1
  • 2


II . 扩展接收者 与 分发接收者 注意事项



1 . 扩展函数 / 属性 中可以调用 扩展接收者 与 分发接收者 两个对象的成员 : 如上面的 Teach.teach 扩展函数中 , 即可以调用 Teacher ( 扩展接收者 ) 对象的 name 属性 , 也可以调用 Student ( 分发接收者 ) 对象的 name 属性 ;


2 . 扩展接收者 与 分发接收者 的 同名 属性 / 函数 优先级 : 如上面的示例中 , 在扩展中同时调用 二者 的 name 属性 , 默认调用的是扩展接收者 ( 被扩展类对象 ) 的 name 属性 , 如果调用 分发接收者 ( 本类 Student ) 的 name 属性 , 需要使用 this@Student.name 调用 ;

在这里插入图片描述


3 . 扩展作用域 : 在分发接收者类型中定义的扩展 , 只能在该类内部调用 , 在类外部是访问不到的 ; 在上面的示例中注释掉了该行代码 ;

在这里插入图片描述



III . open 修饰 分发接收者 类型中的扩展



情形描述 : 在分发接收者类型中 , 可以使用 open 关键字修饰扩展 , 这个扩展函数 , 可以在子类中重写覆盖 ;


① 代码示例 : Student 使用 open 修饰 , fun Teacher.teach 扩展函数也使用 open 修饰 ; 在子类中可以重写 fun Teacher.teach 扩展函数 ;


//扩展接收者类型 , 为该类扩展函数
class Teacher{
    var name : String = "Jerry"
}

//分发接收者类型 , 在该类中为 Teacher 扩展函数
//  注意将 Student 类也声明成 open 类 , 才能被继承
open class Student{
    var name : String = "Tom"

    // Student 类中的方法
    fun study(){
        println("${name} 在学习")
    }

    /*
        在 Student 类中为 Teacher 类定义扩展函数

        扩展函数内部可以调用 Teacher 和 Student 两个对象的成员
     */
    open fun Teacher.teach(){
        //调用 扩展接收者 的 name 属性
        println("${this.name} 在讲课")

        //调用 分发接收者 的 name 属性
        println("${this@Student.name} 在听课")
    }

    //类内部扩展的函数 , 只能在 分发接收者 对象中调用 , 不能在类外部调用
    fun teachAndStudy(){
        Teacher().teach()
    }
}

//Student 子类 , 其中重写了扩展
class MaleStudent : Student(){
    override fun Teacher.teach() {
        //调用 扩展接收者 的 name 属性
        println("${this.name} 在讲课")

        //调用 分发接收者 的 name 属性
        println("男学生 ${this@MaleStudent.name} 在听课")
    }
}

fun main() {
    Student().teachAndStudy()
    //子类中调用了子类重写的扩展函数
    MaleStudent().teachAndStudy()

    //在分发接收者类型中定义的扩展 ,
    // 只能在该类内部调用 , 在类外部是访问不到的
    //Teacher().teach()
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

② 执行结果 :

Jerry 在讲课
Tom 在听课
Jerry 在讲课
男学生 Tom 在听课

  
 
  • 1
  • 2
  • 3
  • 4

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/105275000

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。