【Kotlin】扩展接收者 与 分发接收者 ( 类内部扩展用法 | 注意事项 | open 修饰扩展 )
文章目录
- 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 修饰扩展 )相关推荐
- Kotlin学习笔记(一) 类与对象
类与对象 1. 属性与字段 Getters与Setters set方法与get方法中如果需要用到变量,需要用field来表示当前变量而不能直接引用,否则会造成死循环. 关键字field表示幕后字段,只 ...
- Go 学习笔记(71)— Go 接口 interface (接口定义、接口实现、接口调用、值接收者、指针接收者)
1. 接口的定义 接口是和调用方的一种约定,它是一个高度抽象的类型,不用和具体的实现细节绑定在一起.接口要做的是定义好约定,告诉调用方自己可以做什么,但不用知道它的内部实现,这和我们见到的具体的类型如 ...
- android+广播接收者category,广播接收者
广播接收者 Android: 系统在运行过程中,会产生很多事件,那么某些事件产生时,比如:电量改变,收发短信,拨打电话,屏幕解锁等,开机,系统会发送广播,只要应用程序接收这条广播,就知道系统发生了相应 ...
- 使用扩展方法和静态门面类实现伪领域对象
背景介绍 领域对象,在此特指充血的领域对象模型,在解决什么是伪领域对象之前,需要事先解释何为充血的领域对象.在此后的介绍中,假设我们存在对象模型Employee-Department. 在面向对象的实 ...
- 请确保此代码文件中定义的类与“inherits”属性匹配,并且该类扩展的基类(例如Page 或UserControl)是正确的。...
编译ASP.NET时,提示"请确保此代码文件中定义的类与"inherits"属性匹配,并且该类扩展的基类(例如Page 或UserControl)是正确的.", ...
- 【Groovy】MOP 元对象协议与元编程 ( Groovy 类内部和外部分别获取 metaClass | 分析获取 metaClass 操作的字节码 | HandleMetaClass 注入方法 )
文章目录 一.Groovy 类内部和外部分别获取 metaClass 二.分析 Groovy 类内部和外部获取 metaClass 操作的字节码 三.使用 HandleMetaClass 注入方法 一 ...
- Spring@Cacheable注解在类内部调用失效的问题
如图所示,getRecomendGoogs方法里面调用findImgUrlByName方法,在findImgUrlByName方法上使用@Cacheable注解的时候,并没有走缓存. 要解决这个问题, ...
- java类内部的变量
类内部的变量分为两部分: 一.类的成员变量 在类内部,变量定义部分,定义的变量. 二.局部变量 在类内方法体中定义的变量和方法中涉及的变量. 成员变量和局部变量的区别: (1)成员变量在整个类中都有效 ...
- 快来看一看String类内部是如何实现的
String类内部实现 在C语言初识阶段,对于一些字符串的处理,往往做法是将其转换为单个字符通过遍历来进行逐个处理,但此做法需要耗费大量的计算量,如果字符串过长,导致时间甚至内存都会被大量浪费 学习到 ...
最新文章
- java调用cd传输_Java调用Linux命令(cd的处理)
- 360 与QQ 互掐 受害的却是用户
- 根据 中序遍历 和 后序遍历构造树(Presentation)(C++)
- Java程序在命令行的编译运行
- 21种mysql_让MySQL飞起来!别小看这21种写SQL的好习惯
- Springboot-importSelector
- 【API进阶之路】高考要考口语?我用多模态评测API做了一场10w+刷屏活动
- Git_自定义Git
- 《重构》-重新组织函数
- @扎克伯格:一句对不起,能挽回我们泄漏的数据吗?
- V-rep学习笔记:机器人逆运动学数值解法(Damped Least Squares / Levenberg-Marquardt Method)...
- 如何在VS2015创建C语言项目
- STM32cube配置编码器和电机
- 电脑重启命令c语言,命令提示符重启电脑_命令提示符 重启
- win10 远程桌面卡顿_主编教你win10系统使用远程桌面卡顿的步骤
- 自动排单功能的一些思考
- Bootstrap实战---footer处理
- 什么是动态代理,动态代理的应用有哪些
- 贫富分化是生产力发展的必然趋势 zz
- Java实现字典树 Trie
热门文章
- WPF error: does not contain a static 'Main' method suitable for an entry point
- Android性能测试-分析工具
- 5. [mmc subsystem] mmc core(第五章)——card相关模块(mmc type card)
- Swig在Mac OS X上的安装
- jedis操作redis(一)
- CentOS进不了mysql
- GoldenGate 配置extract,replicat进程自启动
- C#正则表达式提取HTML中IMG标签的SRC地址(转)
- Linux下查看操作系统的位数和系统名称版本信息
- 使用VS2012进行性能测试和负载测试