1.并非面向对象中的“对象” 而是指 Kotlin 中用 object 关键字声明的结构
2.可用来声明单例类,也可包装数据,还能充当匿名内部类
3.匿名对象可以用作只在本地和私有作用域中声明的类型。如果你使用匿名对象作为公有函数的返回类型或者用作公有属性的类型,那么该函数或属性的实际类型会是匿名对象声明的超类型,如果你没有声明任何超类型,就会是
Any。在匿名对象中添加的成员将无法访问4.对象声明是在第一次被访问到时延迟初始化的
5.伴生对象的初始化是在相应的类被加载(解析)时,与 Java 静态初始化器的语义相匹配
// 要创建一个继承自某个(或某些)类型的匿名类的对象
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) { …… }
override fun mouseEntered(e: MouseEvent) { …… }
})
//如果超类型有一个构造函数,则必须传递适当的构造函数参数给它。 多个超类型可以由跟在冒号后面的逗号分隔的列表指定
open class A(x: Int) {
public open val y: Int = x
}
interface B { …… }
val ab: A = object : A(1), B {
override val y = 15
}
// 简单对象
fun foo() {
val adHoc = object {
var x: Int = 0
var y: Int = 0
}
print(adHoc.x + adHoc.y)
}
// 匿名对象
class C {
// 私有函数,所以其返回类型是匿名对象类型
private fun foo() = object {
val x: String = "x"
}
// 公有函数,所以其返回类型是 Any
fun publicFoo() = object {
val x: String = "x"
}
fun bar() {
val x1 = foo().x // 没问题
val x2 = publicFoo().x // 错误:未能解析的引用“x”
}
}
对象声明
1.object 关键字后跟一个名称
2.对象声明的初始化过程是线程安全的
// 定义
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
// ……
}
val allDataProviders: Collection<DataProvider>
get() = // ……
}
// 调用
DataProviderManager.registerDataProvider(……)
// object 继承
open class A {
open fun show() {
print("2222")
}
}
object AObject: A() {
override fun show() {
super.show()
print("111")
}
}
fun main() {
AObject.show() // 2222111
}
伴生对象
1.类内部的对象声明可以用 companion 关键字标记
2.伴生对象的成员可通过只使用类名作为限定符来调用
3.可以省略伴生对象的名称,在这种情况下将使用名称
Companion4.伴生对象的成员看起来像其他语言的静态成员,在运行时他们仍然是真实对象的实例成员
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
//调用
val instance = MyClass.create()
class MyClass {
companion object {
fun create(): MyClass = MyClass()
}
}
val x = MyClass.Companion
// 实现接口
interface Factory<T> {
fun create(): T
}
class MyClass {
companion object : Factory<MyClass> {
override fun create(): MyClass = MyClass()
}
}
val f: Factory<MyClass> = MyClass