跳到主要内容

Kotlin 对象声明和表达式

提示
  1. 对象声明:Kotlin 使用 object 关键字声明单例类,创建的对象是全局唯一的。这种方式适合在程序中需要一个共享资源或单例模式的场合。
  2. 对象表达式:使用 object 关键字还可以创建匿名类的对象(匿名对象),用于扩展现有类或实现接口,而无需显式声明新的子类。
  3. 应用场景:对象声明适用于单例模式,而对象表达式适合在需要类的简单修改或临时实现时使用,如创建监听器或各种适配器。

对象声明

单例是一种面向对象的模式,其中一个类只能有一个实例(对象)。

例如,你正在开发一个具有 SQL 数据库后端的应用程序。你想创建一个连接池来访问数据库,同时为所有客户端重用同一个连接。为此,你可以通过单例类创建连接,以便每个客户端获得相同的连接。

Kotlin 使用对象声明特性提供了一种简单的方式来创建单例。为此,使用 object 关键字。

object SingletonExample {
... .. ...
// 类的主体
... .. ...
}

上述代码结合了一个类声明和该类的单个实例 SingletonExample 的声明。

对象声明可以包含属性、方法等。然而,它们不允许拥有构造器(这是有意义的)。为什么?

类似于普通类的对象,你可以使用 . 符号调用方法和访问属性。

示例:对象声明

object Test {
private var a: Int = 0
var b: Int = 1

fun makeMe12(): Int {
a = 12
return a
}
}

fun main(args: Array<String>) {
val result: Int

result = Test.makeMe12()

println("b = ${Test.b}")
println("result = $result")
}

当你运行程序时,输出将是:

b = 1
result = 12

对象声明可以像普通类一样继承自类和接口。

单例和依赖注入

对象声明有时可能很有用。然而,在与系统的许多其他部分交互的大型软件系统中,它们并不理想。

推荐阅读:依赖注入 & 单例设计模式

Kotlin 对象表达式

object 关键字也可以用来创建匿名类的对象,称为匿名对象。如果你需要为某个类或接口创建一个稍作修改的对象,而不声明它的子类,就会使用它们。例如,

window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}

override fun mouseEntered(e: MouseEvent) {
// ...
}
})

(该示例取自官方 Kotlin 文档页面。)

这里,声明了一个扩展 MouseAdapter 类的匿名对象。程序重写了两个 MouseAdapter 方法:mouseClicked()mouseEntered()。 如果需要,您可以为匿名对象指定一个名称,并将其存储在变量中。例如,

val obj = object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}

override fun mouseEntered(e: MouseEvent) {
// ...
}
}

示例:Kotlin 对象表达式

open class Person() {
fun eat() = println("吃食物。")

fun talk() = println("与人交谈。")

open fun pray() = println("祈祷上帝。")
}

fun main(args: Array<String>) {
val atheist = object : Person() {
override fun pray() = println("我不祈祷。我是无神论者。")
}

atheist.eat()
atheist.talk()
atheist.pray()
}

当你运行程序时,输出将是:

吃食物。
与人交谈。
我不祈祷。我是无神论者。

在这里,匿名对象被存储在变量 atheist 中,它实现了 Person 类,并重写了 pray() 方法。

如果您要实现一个具有构造函数的类来声明匿名对象,则需要传递适当的构造函数参数。例如,

open class Person(name: String, age: Int) {

init {
println("姓名:$name,年龄:$age")
}

fun eat() = println("吃食物。")
fun talk() = println("与人交谈。")
open fun pray() = println("祈祷上帝。")
}

fun main(args: Array<String>) {
val atheist = object : Person("Jack", 29) {
override fun pray() = println("我不祈祷。我是无神论者。")
}

atheist.eat()
atheist.talk()
atheist.pray()
}

当你运行程序时,输出将是:

姓名:Jack,年龄:29
吃食物。
与人交谈。
我不祈祷。我是无神论者。