文章目录

  • I . 类内部扩展其它类
  • II . 扩展接收者 与 分发接收者 注意事项
  • III . open 修饰 分发接收者 类型中的扩展

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()
}

执行结果 :

Jerry 在讲课
Tom 在听课

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()
}

② 执行结果 :

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

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

  1. Kotlin学习笔记(一) 类与对象

    类与对象 1. 属性与字段 Getters与Setters set方法与get方法中如果需要用到变量,需要用field来表示当前变量而不能直接引用,否则会造成死循环. 关键字field表示幕后字段,只 ...

  2. Go 学习笔记(71)— Go 接口 interface (接口定义、接口实现、接口调用、值接收者、指针接收者)

    1. 接口的定义 接口是和调用方的一种约定,它是一个高度抽象的类型,不用和具体的实现细节绑定在一起.接口要做的是定义好约定,告诉调用方自己可以做什么,但不用知道它的内部实现,这和我们见到的具体的类型如 ...

  3. android+广播接收者category,广播接收者

    广播接收者 Android: 系统在运行过程中,会产生很多事件,那么某些事件产生时,比如:电量改变,收发短信,拨打电话,屏幕解锁等,开机,系统会发送广播,只要应用程序接收这条广播,就知道系统发生了相应 ...

  4. 使用扩展方法和静态门面类实现伪领域对象

    背景介绍 领域对象,在此特指充血的领域对象模型,在解决什么是伪领域对象之前,需要事先解释何为充血的领域对象.在此后的介绍中,假设我们存在对象模型Employee-Department. 在面向对象的实 ...

  5. 请确保此代码文件中定义的类与“inherits”属性匹配,并且该类扩展的基类(例如Page 或UserControl)是正确的。...

    编译ASP.NET时,提示"请确保此代码文件中定义的类与"inherits"属性匹配,并且该类扩展的基类(例如Page 或UserControl)是正确的.", ...

  6. 【Groovy】MOP 元对象协议与元编程 ( Groovy 类内部和外部分别获取 metaClass | 分析获取 metaClass 操作的字节码 | HandleMetaClass 注入方法 )

    文章目录 一.Groovy 类内部和外部分别获取 metaClass 二.分析 Groovy 类内部和外部获取 metaClass 操作的字节码 三.使用 HandleMetaClass 注入方法 一 ...

  7. Spring@Cacheable注解在类内部调用失效的问题

    如图所示,getRecomendGoogs方法里面调用findImgUrlByName方法,在findImgUrlByName方法上使用@Cacheable注解的时候,并没有走缓存. 要解决这个问题, ...

  8. java类内部的变量

    类内部的变量分为两部分: 一.类的成员变量 在类内部,变量定义部分,定义的变量. 二.局部变量 在类内方法体中定义的变量和方法中涉及的变量. 成员变量和局部变量的区别: (1)成员变量在整个类中都有效 ...

  9. 快来看一看String类内部是如何实现的

    String类内部实现 在C语言初识阶段,对于一些字符串的处理,往往做法是将其转换为单个字符通过遍历来进行逐个处理,但此做法需要耗费大量的计算量,如果字符串过长,导致时间甚至内存都会被大量浪费 学习到 ...

最新文章

  1. java调用cd传输_Java调用Linux命令(cd的处理)
  2. 360 与QQ 互掐 受害的却是用户
  3. 根据 中序遍历 和 后序遍历构造树(Presentation)(C++)
  4. Java程序在命令行的编译运行
  5. 21种mysql_让MySQL飞起来!别小看这21种写SQL的好习惯
  6. Springboot-importSelector
  7. 【API进阶之路】高考要考口语?我用多模态评测API做了一场10w+刷屏活动
  8. Git_自定义Git
  9. 《重构》-重新组织函数
  10. @扎克伯格:一句对不起,能挽回我们泄漏的数据吗?
  11. V-rep学习笔记:机器人逆运动学数值解法(Damped Least Squares / Levenberg-Marquardt Method)...
  12. 如何在VS2015创建C语言项目
  13. STM32cube配置编码器和电机
  14. 电脑重启命令c语言,命令提示符重启电脑_命令提示符 重启
  15. win10 远程桌面卡顿_主编教你win10系统使用远程桌面卡顿的步骤
  16. 自动排单功能的一些思考
  17. Bootstrap实战---footer处理
  18. 什么是动态代理,动态代理的应用有哪些
  19. 贫富分化是生产力发展的必然趋势 zz
  20. Java实现字典树 Trie

热门文章

  1. WPF error: does not contain a static 'Main' method suitable for an entry point
  2. Android性能测试-分析工具
  3. 5. [mmc subsystem] mmc core(第五章)——card相关模块(mmc type card)
  4. Swig在Mac OS X上的安装
  5. jedis操作redis(一)
  6. CentOS进不了mysql
  7. GoldenGate 配置extract,replicat进程自启动
  8. C#正则表达式提取HTML中IMG标签的SRC地址(转)
  9. Linux下查看操作系统的位数和系统名称版本信息
  10. 使用VS2012进行性能测试和负载测试