使用 object 关键字有三种方式: 单例类、对象表达式和伴生对象( companion object)。下面我们就来逐一学习使用它们:
1、单例类
在Kotlin里使用单例,在类名前面加一个object关键字就可以实现单例了:
反编译成java代码来看下:
可以看到,本质上是使用Java的 静态内部类写法 来实现单例的。
2、对象表达式
这个匿名类依然遵循 object 关键字的一个规则,即一旦实例化,该匿名类只能有唯一一个实例存在。当然,它的生命周期或作用范围要远远小于命名单例。取决于在哪里定义,对象表达式会受副作用影响而有不同的初始化表现。
如果定义在独立文件里,对象表达式会立即初始化;
如果定义在另一个类里,那么只有包含它的类初始化时,对象表达式才会被初始化。
3、伴生对象
如果你想将某个对象的初始化和一个类实例捆绑在一起,可以考虑使用伴生对象。使用companion 修饰符,你可以在一个类定义里声明一个伴生对象。一个类里只能有一个伴生对象。
伴生对象初始化也分两种情况:
第一种,包含伴生对象的类初始化时,伴生对象就会被初始化。由于这种相伴关系,伴生对象就适合用来存放和类定义有上下文关系的单例数据。
第二种,只要直接访问伴生对象的某个属性或函数,就会触发伴生对象的初始化。
伴生对象本质上依然是个对象声明,所以不需要使用类实例来访问它内部定义的函数或属性。以下是一个伴生对象示例,它定义在一个叫 PremadeWorldMap 的类里:
这个伴生对象里定义了一个叫作 load 的函数。如果想调用 load 函数, 无须 PremadeWorldMap 类实例,像下面这样直接调用 PremadeWorldMap.load()。
按照上面说的两种情况,只有初始化 PremadeWorldMap 类或调用 load 函数时,伴生对象的内容才会载入。而且,无论实例化 PremadeWorldMap 类多少次,这个伴生对象始终只有一个实例存在。