Kotlin 语言参考文档 中文版 Help

对象

在这一章中, 你将探索对象声明, 扩展对类的理解. 这些知识将帮助你高效的管理整个项目的行为.

对象声明

在 Kotlin 中, 你可以使用 对象 声明 来声明一个只有唯一实例的类. 从某种意义上说, 你在声明类的 同时 也就创建了唯一的实例. 当你想要创建一个类, 并以你的程序中的唯一引用点的方式使用它, 或者想要协调它在整个系统中的行为, 对象声明会非常有用.

Kotlin 中的对象是 延迟加载(lazy) 的, 意思就是说, 它们只在被访问的时候才创建. Kotlin 还会确保所有的对象以线程安全的方式创建, 因此你不必手动检查.

要创建一个对象声明, 请使用 object 关键字:

object DoAuth {}

之后是你的 object 的名称, 并在大括号 {} 表示的对象 body 部中添加属性或成员函数.

例如, 假设你想要创建一个对象, 名为 DoAuth, 负责身份验证:

object DoAuth { fun takeParams(username: String, password: String) { println("input Auth parameters = $username:$password") } } fun main(){ // 当 takeParams() 函数被调用时, 对象被创建 DoAuth.takeParams("coding_ninja", "N1njaC0ding!") // 输出结果为: input Auth parameters = coding_ninja:N1njaC0ding! }

这个对象有一个成员函数, 名为 takeParams, 参数是 username 和 password 变量, 并打印一个字符串到控制台. 只有在函数初次被调用时, DoAuth 对象才会被创建.

数据对象(Data Object)

为了更容易的打印输出对象声明的内容, Kotlin 提供了 数据(Data) 对象. 与你在初学者教程中学过的数据类类似, 数据对象自动带有额外的成员函数: toString() 和 equals().

要创建一个数据对象, 请使用与对象声明相同的语法, 但前面加上 data 关键字:

data object AppConfig {}

例如:

data object AppConfig { var appName: String = "My Application" var version: String = "1.0.0" } fun main() { println(AppConfig) // 输出结果为: AppConfig println(AppConfig.appName) // 输出结果为: My Application }

关于数据对象, 详情请参见 数据对象.

同伴对象(Companion Object)

在 Kotlin 中, 一个类可以带有一个对象: 一个 同伴(Companion) 对象. 对每个类, 你只能有 一个 同伴对象. 只有在类初次被引用时, 同伴对象才会被创建.

在同伴对象之内声明的任何属性或函数, 都在类的所有实例之间共享.

要在一个类之内创建一个同伴对象, 请使用与对象声明相同的语法, 但前面加上 companion 关键字:

companion object Bonger {}

要访问同伴对象的任何属性或函数, 请通过类名称来引用它. 例如:

class BigBen { companion object Bonger { fun getBongs(nTimes: Int) { repeat(nTimes) { print("BONG ") } } } } fun main() { // 当类初次被引用时, 同伴对象被创建. BigBen.getBongs(12) // 输出结果为: BONG BONG BONG BONG BONG BONG BONG BONG BONG BONG BONG BONG }

这个示例创建了一个类, 名为 BigBen, 它包含一个同伴对象, 名为 Bonger. 同伴对象有一个成员函数, 名为 getBongs(), 接受一个整数参数, 并打印 "BONG" 到控制台, 打印次数与整数参数相同.

在 main() 函数 中, 通过类的名称调用了 getBongs() 函数. 同伴对象会在这个时候被创建. 调用 getBongs() 函数的参数是 12.

详情请参见 同伴对象(Companion Object).

实际练习

习题 1

你运营着一个咖啡店, 并有一个系统来追踪客户订单. 请参考下面的代码, 并完成第 2 个数据对象的声明, 让 main() 函数中的以下代码成功运行:

interface Order { val orderId: String val customerName: String val orderTotal: Double } data object OrderOne: Order { override val orderId = "001" override val customerName = "Alice" override val orderTotal = 15.50 } data object // 请在这里编写你的代码 fun main() { // 打印输出每个数据对象的名称 println("Order name: $OrderOne") // 输出结果为: Order name: OrderOne println("Order name: $OrderTwo") // 输出结果为: Order name: OrderTwo // 检查订单是否相同 println("Are the two orders identical? ${OrderOne == OrderTwo}") // 输出结果为: Are the two orders identical? false if (OrderOne == OrderTwo) { println("The orders are identical.") } else { println("The orders are unique.") // 输出结果为: The orders are unique. } println("Do the orders have the same customer name? ${OrderOne.customerName == OrderTwo.customerName}") // 输出结果为: Do the orders have the same customer name? false }
interface Order { val orderId: String val customerName: String val orderTotal: Double } data object OrderOne: Order { override val orderId = "001" override val customerName = "Alice" override val orderTotal = 15.50 } data object OrderTwo: Order { override val orderId = "002" override val customerName = "Bob" override val orderTotal = 12.75 } fun main() { // 打印输出每个数据对象的名称 println("Order name: $OrderOne") // 输出结果为: Order name: OrderOne println("Order name: $OrderTwo") // 输出结果为: Order name: OrderTwo // 检查订单是否相同 println("Are the two orders identical? ${OrderOne == OrderTwo}") // 输出结果为: Are the two orders identical? false if (OrderOne == OrderTwo) { println("The orders are identical.") } else { println("The orders are unique.") // 输出结果为: The orders are unique. } println("Do the orders have the same customer name? ${OrderOne.customerName == OrderTwo.customerName}") // 输出结果为: Do the orders have the same customer name? false }

习题 2

创建一个对象声明, 继承自 Vehicle 接口, 以创建一个唯一的车辆类型: FlyingSkateboard. 实现你的对象中的 name 属性和 move() 函数, 让 main() 函数中的以下代码成功运行:

interface Vehicle { val name: String fun move(): String } object // 请在这里编写你的代码 fun main() { println("${FlyingSkateboard.name}: ${FlyingSkateboard.move()}") // 输出结果为: Flying Skateboard: Glides through the air with a hover engine println("${FlyingSkateboard.name}: ${FlyingSkateboard.fly()}") // 输出结果为: Flying Skateboard: Woooooooo }
interface Vehicle { val name: String fun move(): String } object FlyingSkateboard : Vehicle { override val name = "Flying Skateboard" override fun move() = "Glides through the air with a hover engine" fun fly(): String = "Woooooooo" } fun main() { println("${FlyingSkateboard.name}: ${FlyingSkateboard.move()}") // 输出结果为: Flying Skateboard: Glides through the air with a hover engine println("${FlyingSkateboard.name}: ${FlyingSkateboard.fly()}") // 输出结果为: Flying Skateboard: Woooooooo }

习题 3

你在为一个 App 构建用户注册模块. 你想要将 EMail 验证逻辑与 User 类关联起来, 但如果 EMail 地址无效, 不想创建不必要的 User 实例.

在这个习题中, 如果 EMail 地址同时包含 @ 和 ., 则认为有效. 请完成数据类, 让 main() 函数中的以下代码成功运行:

提示

在 `User` 类的同伴对象中添加 EMail 验证函数, 这样就可以直接在 `User` 类上调用函数.

data class User(val name: String, val email: String) { // 请在这里编写你的代码 } fun main() { val candidates = listOf( Pair("Alice", "alice@example.com"), Pair("Bob", "bob2example-com") ) for ((name, email) in candidates) { if (User.isValidEmail(email)) { val user = User(name, email) println("Registered: ${user.name}, ${user.email}") // 输出结果为: Registered: Alice, alice@example.com } else { println("Error: '${email}' is not valid. The email should contain '@' and '.'") // 输出结果为: Error: 'bob2example-com' is not valid. The email should contain '@' and '.' } } }
data class User(val name: String, val email: String) { companion object { fun isValidEmail(email: String): Boolean = email.contains('@') && email.contains('.') } } fun main() { val candidates = listOf( Pair("Alice", "alice@example.com"), Pair("Bob", "bob2example-com") ) for ((name, email) in candidates) { if (User.isValidEmail(email)) { val user = User(name, email) println("Registered: ${user.name}, ${user.email}") // 输出结果为: Registered: Alice, alice@example.com } else { println("Error: '${email}' is not valid. The email should contain '@' and '.'") // 输出结果为: Error: 'bob2example-com' is not valid. The email should contain '@' and '.' } } }

下一步

中级教程: 开放类与特殊类

2026/09/29