ZetCode

Kotlin Object 关键字

最后修改于 2025 年 4 月 19 日

Kotlin 的 object 关键字是一个强大的特性,它支持多种模式。它可以创建单例、伴生对象和匿名对象。本教程将通过示例深入探讨 object 关键字。

基本定义

Kotlin 中的 object 关键字有三个主要用途。它可以声明单例对象,创建伴生对象和形成对象表达式。每个用途在 Kotlin 编程中都有不同的作用。

单例对象

object 最简单的用法是创建单例。单例是一个只有单个实例的类。Kotlin 使单例的实现变得容易。

Singleton.kt
package com.zetcode

object DatabaseManager {
    private val connections = mutableListOf<String>()
    
    fun addConnection(conn: String) {
        connections.add(conn)
    }
    
    fun listConnections() {
        connections.forEach { println(it) }
    }
}

fun main() {
    DatabaseManager.addConnection("Connection 1")
    DatabaseManager.addConnection("Connection 2")
    DatabaseManager.listConnections()
}

在这里,我们使用 object 关键字创建一个 DatabaseManager 单例。它维护一个连接列表。我们无需实例化它即可直接访问其方法。该对象在首次访问时被懒加载创建。

伴生对象

伴生对象使用 companion 修饰符在类内部声明。它们可以访问包含类的私有成员并用作工厂方法。

CompanionObject.kt
package com.zetcode

class User private constructor(val name: String) {
    companion object {
        fun create(name: String): User {
            return User(name)
        }
        
        const val MAX_AGE = 120
    }
}

fun main() {
    val user = User.create("John Doe")
    println(user.name) // Output: John Doe
    println(User.MAX_AGE) // Output: 120
}

此示例展示了一个带有私有构造函数的 User 类。伴生对象提供了一个工厂方法 create 和一个常量。我们使用类名作为限定符来访问伴生成员。

对象表达式

对象表达式创建匿名对象,类似于 Java 的匿名类。它们对于接口或抽象类的一次性实现很有用。

ObjectExpression.kt
package com.zetcode

interface ClickListener {
    fun onClick()
}

fun main() {
    val button = object : ClickListener {
        override fun onClick() {
            println("Button clicked!")
        }
    }
    
    button.onClick() // Output: Button clicked!
}

在这里,我们创建一个实现 ClickListener 接口的匿名对象。对象表达式语法允许我们同时定义和实例化一个类。这对于事件处理程序和回调很有用。

带名称的伴生对象

伴生对象可以有名称,这允许它们实现接口或扩展类。命名的伴生对象比未命名的伴生对象更灵活。

NamedCompanion.kt
package com.zetcode

interface Factory<T> {
    fun create(): T
}

class Product {
    companion object ProductFactory : Factory<Product> {
        override fun create(): Product {
            return Product()
        }
    }
}

fun main() {
    val product = Product.create()
    println(product::class.simpleName) // Output: Product
}

此示例显示了一个名为 ProductFactory 的伴生对象,它实现了 Factory 接口。伴生对象提供了一个类型安全的工厂方法。代码中可以引用命名的伴生对象。

带属性的对象声明

对象可以拥有属性、方法、初始化程序,并且可以实现接口。它们是具有 Kotlin 保证的单个实例的完整类。

ObjectProperties.kt
package com.zetcode

object Configuration {
    private const val FILE = "config.json"
    
    var timeout: Int = 1000
    val isDebug: Boolean
        get() = System.getProperty("debug") == "true"
    
    init {
        println("Configuration loaded from $FILE")
    }
    
    fun logSettings() {
        println("Timeout: $timeout, Debug: $isDebug")
    }
}

fun main() {
    Configuration.timeout = 2000
    Configuration.logSettings()
}

Configuration 对象演示了各种特性。它具有属性、自定义 getter、一个初始化块和方法。该对象在首次访问时被初始化,并且 init 块仅运行一次。

带有超类型的对象表达式

对象表达式可以同时扩展一个类和实现接口。这为创建即席实现提供了极大的灵活性。

ObjectSupertype.kt
package com.zetcode

open class Person(val name: String) {
    open fun greet() = println("Hello, I'm $name")
}

interface Worker {
    fun work()
}

fun main() {
    val employee = object : Person("Alice"), Worker {
        override fun greet() {
            println("Hi, I'm employee $name")
        }
        
        override fun work() {
            println("$name is working hard")
        }
    }
    
    employee.greet() // Output: Hi, I'm employee Alice
    employee.work()  // Output: Alice is working hard
}

此对象表达式创建了一个匿名类,该类扩展了 Person 并实现了 Worker。它覆盖了这两个类的方法。该语法允许简洁地创建复杂的单次实现。

伴生对象扩展

伴生对象可以用附加函数进行扩展,类似于常规的类扩展。这对于向类添加实用函数很有用。

CompanionExtension.kt
package com.zetcode

class MathUtils {
    companion object {
        fun square(n: Int) = n * n
    }
}

fun MathUtils.Companion.cube(n: Int) = n * n * n

fun main() {
    println(MathUtils.square(3)) // Output: 9
    println(MathUtils.cube(3))   // Output: 27
}

在这里,我们使用 cube 函数扩展了 MathUtils 的伴生对象。扩展函数在伴生对象上可用。这种模式将相关函数保持在一起,同时分离了它们的定义。

Object 关键字的最佳实践

来源

Kotlin 对象声明文档

本教程深入介绍了 Kotlin 的 object 关键字,展示了单例、伴生对象和对象表达式。我们探讨了各种场景,包括命名的伴生对象、扩展和接口实现。object 关键字在 Kotlin 中是多功能且必不可少的。

作者

我的名字是 Jan Bodnar,我是一位充满激情的程序员,拥有多年的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我撰写了 1400 多篇文章和 8 本电子书。我拥有超过八年的编程教学经验。

列出 所有 Kotlin 教程