参考原文:http://kotlinlang.org/docs/reference/object-declarations.html
有时,需要修改一个类的部分功能,可以不通过显式实现一个该类的子类方式来实现。在Java中,通过匿名内部类来实现;在Kotlin中,概括为对象表达式和对象声明(object expressions and object declarations)。
对象表达式(Object expressions)
创建继承一个或多个类型的匿名类:
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
}
有时,只需要一个对象表达式,不想继承任何的父类型,实现如下:
val adHoc = object {
var x: Int = 0
var y: Int = 0
}
print(adHoc.x + adHoc.y)
类似于Java的匿名内部类,对象表达式也可以访问闭合范围内局部变量(跟Java不同,变量不用声明为 final):
fun countClicks(window: JComponent) {
var clickCount = 0
var enterCount = 0
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
clickCount++
}
override fun mouseEntered(e: MouseEvent) {
enterCount++
}
})
// ...
}
对象声明(Object declarations)
单例(Singleton)是一个非常有用的设计模式,在Kotlin中,可以通过下面方式很容易去实现:object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
// ...
}
val allDataProviders: Collection<DataProvider>
get() = // ...
}
object DefaultListener : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
override fun mouseEntered(e: MouseEvent) {
// ...
}
}
注:对象声明( object declaration)不能够定义为局部的(如嵌套在一个函数中),但可以嵌套到其他的对象声明( object declaration)或非内部类中。
友元(伴侣)对象(Companion Objects)
使用“ companion ”关键字修饰,定义在一个类中的对象声明。class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
友元(伴侣)对象的成员,可以通过外部类的类名直接访问:
val instance = MyClass.create()
友元(伴侣)对象的名称,也可以省略,通过“Companion
”关键字访问该友元(伴侣)对象:
class MyClass {
companion object {
}
}
val x = MyClass.Companion
友元(伴侣)对象的成员看起来跟其他语言(如Java)的static成员类型;但是在运行时,它是真正的对象的成员实例;还可以实现接口:
interface Factory<T> {
fun create(): T
}
class MyClass {
companion object : Factory<MyClass> {
override fun create(): MyClass = MyClass()
}
}
注:在Java虚拟机(JVM )中,可以将友元(伴侣)对象的成员使用“@JvmStatic”注解,就可以当做一个真正的静态变量或方法。
对象表达式和对象声明在语义上的区别
Semanticdifference between object expressions and declarations
Ø 对象表达式,在它们使用的地方,是立即(immediately)执行(或初始化)。
Ø 对象声明,会延迟(lazily)初始化;但第一次访问该对象声明时才执行。
Ø 友元对象(Companion Objects),当外部类被加载通过Java静态初始化方式,会延迟初始化。