目录

  • 1. 基本用法
  • 2. 实现接口
  • 3. 伴生对象扩展

伴生对象最简单直白的理解就是与一个类相伴而生的对象,由于它处于类内部,所以必然和包含它的类存在某种联系。

1. 基本用法

伴生对象使用关键字companion来声明,看起来就像是在object关键字前面加的一个修饰符。它的一般格式如下:

class 外部类名{companion object 伴生对象名{//属性//方法}
}

简单的代码示例如下

    companion <span class="hljs-class"><span class="hljs-keyword">object</span> {</span>fun test(){println(<span class="hljs-string">"Companion Object..."</span>)}}
}

你会发现上面的代码中没有伴生对象名,因为它是可以省略的。下面就依次看看伴生对象都用在那些地方。

在Java中有static关键字表示静态成属性和方法,但在Kotlin中没有static关键字,所以伴生对象和顶层函数一起来弥补了这一缺憾,还是看上面给出的第一个例子,那我们怎么去调用伴生对象中的方法呢。

上面的代码连伴生对象的名字都省略了,所以我们只能通过外部类来调用。格式如下:

外部类.伴生对象内部方法

如下所示:

fun main(args: <span class="hljs-keyword">Array</span>&lt;<span class="hljs-keyword">String</span>&gt;) <span class="hljs-list">{A.test()
}

当然对于指定了伴生对象名的情况,调用格式如下:

外部类.伴生对象名.伴生对象内部方法

代码示例如下:

class B{companion object KB{fun testB(){println("Companion Object...")}}
}fun main(args: Array<String>) {B.testB()B.KB.testB()
}

当然你会发现,你在调用时仍然可以省略掉伴生对象名,就像Java中通过类名直接调用静态方法一样。
当然,对于在声明时省略了伴生对象名的情况,Kotlin也提供了一个叫Companion的默认名称,所以我们也可以像下面的方式进行调用:

class A{companion object {fun test(){println("Companion Object...")}}
}fun main(args: Array<String>) {A.test()//默认名称A.Companion.test()
}

其实伴生对象的出现也是为了弥补顶层函数的不足,顶层函数不能访问一个类中的private成员,而伴生对象是可以访问的,如下面代码所示:

class C{private val age: Int = 0;companion object {fun out(){//伴生对象中可以调用外部的私有成员println(C().age)}}
}fun main(args: Array<String>) {//顶层函数不能调用外部类的私有成员println(C().age) //报错
}

2. 实现接口

伴生对象在声明的时候可以像其他类那样实现接口,并实现接口中的方法,如下面的代码所示:

class People(val name: String){//伴生对象实现接口companion object : Log{//实现接口的方法override fun printLog(msg: String) {println("msg ------- $msg")}}
}//该方法的参数是接口实例
fun callLog(log: Log){log.printLog("msg")
}fun main(args: Array<String>) {//传入实现接口的伴生对象的类callLog(People)
}

上面的代码可以这样理解,伴生对象实现了接口,伴生对象又与外部类存在关联,所以相当于外部类也实现了接口,所以我们可直接传入外部类的名称,这里的这个名称就指代了那个伴生对象。

3. 伴生对象扩展

在前面的内容中我们也说过方法扩展,那这里我们的伴生对象也可以进行扩展,我们可以在其上扩展我们自己的方法。这里所谓的扩展就是在声明伴生对象的时候没有指定函数,而是在类的外部来给伴生对象增加方法,来看看下面的代码示例:

class Person(val name: String){companion object {//伴生对象内部没有方法}
}//伴生对象扩展方法
fun Person.Companion.toJson(person: Person): String{//具体实现return "";
}fun main(args: Array<String>) {//调用方法val str = Person.toJson(Person("小白"))
}

上面的扩展方法和函数的扩展差别不大,主要是要访问到扩展对象再在其上扩展方法。

kotlin学习之伴生对象(十五)相关推荐

  1. 未处理异常和C++异常——Windows核心编程学习手札之二十五

    未处理异常和C++异常 --Windows核心编程学习手札之二十五 当一个异常过滤器返回EXCEPTION_CONTINUE_SEARCH标识符时是告诉系统继续上溯调用树,寻找另外的异常过滤器,但当每 ...

  2. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十五章:第一人称摄像机和动态索引...

    Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十五章:第一人称摄像机和动态索引 原文:Introduction to 3 ...

  3. 学习进度条(第十五周)

    学习进度条(第十五周) 所用时间:15小时左右 代码量:185行 博客量:3篇 收获知识:阅读<梦断代码>体会程序员的精彩经历,学会如何项目总结. 转载于:https://www.cnbl ...

  4. LINUX学习基础篇(十五)软件包管理

    LINUX学习基础篇(十五)软件包管理 软件包管理 软件包分类 源码包 二进制包 选择 依赖性 rpm包安装 rpm包命名规则 rpm包安装和卸载 服务命令 rpm查询命令 验证 数字证书 rpm中文 ...

  5. 深度学习入门笔记(十五):深度学习框架(TensorFlow和Pytorch之争)

    欢迎关注WX公众号:[程序员管小亮] 专栏--深度学习入门笔记 声明 1)该文章整理自网上的大牛和机器学习专家无私奉献的资料,具体引用的资料请看参考文献. 2)本文仅供学术交流,非商用.所以每一部分具 ...

  6. 动手深度学习笔记(四十五)8.1. 序列模型

    动手深度学习笔记(四十五)8.1. 序列模型 8.1. 序列模型 8.1.1. 统计工具 8.1.1.1. 自回归模型 8.1.1.2. 马尔可夫模型 8.1.1.3. 因果关系 8.1.2. 训练 ...

  7. Slicer学习笔记(三十五)slicer学习链接

    Slicer学习笔记(三十五)slicer学习链接 使用方面: 坐标系:https://www.slicer.org/wiki/Coordinate_systems 模块:https://slicer ...

  8. 学习Scala:伴生对象和伴生类之间的关系(二)

    孤立对象是只有一个object关键字修饰的对象,该对象会编译成两个class文件,一个是以孤立对象的名字命名的class, 一个是以孤立对象的名字后面加上一个$ 字符命名的class, 这个class ...

  9. Java学习笔记(三十五)

    在完成对C语言的学习后,我最近开始了对C++和Java的学习,目前跟着视频学习了一些语法,也跟着敲了一些代码,有了一定的掌握程度.现在将跟着视频做的笔记进行整理.本篇博客是整理Java知识点的第三十五 ...

最新文章

  1. 斯坦福SAIL负责人Christopher Manning:语言理解是人机灵魂的桥梁
  2. Labview-浅谈Labview中VISA的设计
  3. 设计模式-创建型-生成器
  4. Intellij 14快捷键
  5. oracle sql 分区查询语句_oracle11g 表分区后的查询语句如何知道是否进行了全表扫描...
  6. 程序填充(指针):3数排序_排序算法之快速排序,它为什么这么快?
  7. rowid 对应mysql_请教一下相当于MySQL中Oracle的RowID
  8. antlr java_使用ANTLR和Java创建外部DSL
  9. 机房合作(一):我怎样做组长(敢于承担责任)
  10. fpga初始化错误_FPGA低温启动失败
  11. centos 最简单的服务程序
  12. LeetCode刷题——283. 移动零
  13. 创新的垃圾处理模式——赛普利
  14. 【语音隐写】基于matlab GUI LSB语音信号数字水印嵌入提取(带面板)【含Matlab源码 1676期】
  15. PhpSpreadsheet设置单元格常用操作汇总
  16. libcef-案例展示-将cef浏览器嵌入到mfc中作为子窗口运行
  17. 异数OS TCP协议栈测试(一)--数据传输篇
  18. 计算机域 用户怎么设置,电脑怎么加域设置
  19. php第三方支付宝支付,第三方对接-支付宝支付接入教程
  20. 2023年天津仁爱学院专升本考试考务费网上缴费的通知

热门文章

  1. boost使用split分割字符串
  2. 玩转Google开源C++单元测试框架Google Test系列(gtest)之八 - 打造自己的单元测试框架
  3. setiosflags(ios::fixed)和setprecision()
  4. leetcode-260.只出现一次的数字 III 解法
  5. Frida基础操作命令
  6. 力扣--替换后的最长重复字符
  7. 北京冬奥黑科技; 揭秘虎年春晚硬核科技;全球首款AR隐形眼镜问世;索尼3D显示技术路径曝光...
  8. LiveVideoStack公众号内容改版通知
  9. JVM之堆Heap参数调优入门
  10. 浅谈 RocketMQ、Kafka、Pulsar 的事务消息