`object` 和 `class` 的关键区别在于:**`class` 是蓝图,用于创建多个实例;而 `object` 是单一实体,本身就是一个唯一的、全局可用的实例**。为了更直观地理解,我们先来看一个对比表格,然后进行详细解释。### `object` 和 `class` 主要区别对比| 特性 | `class` (类) | `object` (对象声明) | `companion object` (伴生对象) | | :--- | :--- | :--- | :--- | | **核心概念** | 创建对象的**蓝图**或模板 | 实现**单例模式**的语法糖 | 属于类的**单例对象**,相当于 Java 的 `static` | | **实例化** | 必须手动实例化 (`val obj = MyClass()`) | **无需且无法**实例化,直接通过名称访问 | **无需且无法**实例化,通过类名直接访问 | | **数量** | 可以创建**多个**实例 | **有且只有一个**全局实例 | **有且只有一个**(依附于所属类) | | **用途** | 定义需要多次实例化的数据结构或行为 | 工具类、全局状态容器、服务访问点 | 工厂方法、类常量、替代 Java 的静态成员 |---### 详细解释和代码示例#### 1. `class` - 需要实例化的模板一个 `class` 只是一个模板或蓝图。要使用它,你必须创建它的实例(对象)。你可以根据需要创建多个实例,每个实例都有自己的状态。```kotlin // 定义一个类 (蓝图) class Car(val brand: String, var speed: Int) {fun accelerate() {speed += 10} }fun main() {// 创建类的多个实例val car1 = Car("Toyota", 0) // 使用构造函数创建实例val car2 = Car("BMW", 50)car1.accelerate()println(car1.speed) // 输出: 10println(car2.speed) // 输出: 50// car1 和 car2 是两个独立的对象println(car1 == car2) // 输出: false } ```#### 2. `object` - 单例(只有一个实例的对象)一个 `object` 声明同时定义了一个类**和它的一个唯一实例**。它用于当你需要且只需要一个某种类型的对象时(单例模式)。你无法创建它的实例,直接通过对象名访问。```kotlin // 定义一个对象声明 (单例) object ApplicationConfig {// 这些属性在整个程序中只有一份val version: String = "1.0.0"var isDebug: Boolean = truefun setup() {println("Application version $version is configured. Debug: $isDebug")} }fun main() {// 直接通过对象名访问,无需实例化println(ApplicationConfig.version) // 输出: 1.0.0ApplicationConfig.setup() // 输出: Application version 1.0.0 is configured. Debug: trueApplicationConfig.isDebug = false // 修改全局状态// 在任何地方访问的都是同一个实例println(ApplicationConfig.isDebug) // 输出: false } ```**常见用途**:工具类(如 `JsonUtils`)、全局配置、服务访问点(如 `DatabaseManager`)、实现接口的单例。#### 3. `companion object` - 类内部的单例(伴生对象)这是一个定义在类内部的 `object`。它允许你调用其成员时**像调用 Java 的静态方法一样**,使用类名作为限定符,但这些成员仍然是真实对象的实例成员。```kotlin class MyClass {// 实例属性,每个实例都有自己的副本val instanceProperty: String = "I belong to an instance" // 伴生对象companion object {// 属于伴生对象的属性,全局只有一份const val CLASS_CONSTANT: String = "I belong to the class"fun create(): MyClass {// 可以访问私有构造函数return MyClass()}} }fun main() { // 通过类名直接访问伴生对象的成员,无需实例化 MyClassprintln(MyClass.CLASS_CONSTANT) // 输出: I belong to the classval obj = MyClass.create() // 调用伴生对象的工厂方法// 实例成员仍需通过实例访问println(obj.instanceProperty) // 输出: I belong to an instance// 错误示例:无法通过类名访问实例成员// println(MyClass.instanceProperty) // 编译错误! } ```**常见用途**: - **工厂方法** (`MyClass.create()`) - **类常量** (`MyClass.CLASS_CONSTANT`) - **替代 Java 的静态方法和字段** - 实现接口(伴生对象可以实现接口,而 Java 的静态方法不能)---### 如何选择?- **需要创建多个具有相同结构但不同状态的对象?** → 使用 `class`。```kotlinclass User(val name: String) // 每个用户都有不同的名字```- **只需要一个全局对象来管理某些状态或提供工具函数?** → 使用 `object`。```kotlinobject Logger {fun log(message: String) { ... }}// 使用:Logger.log("Something happened")```- **需要一些与类相关而不是与实例相关的功能(如常量、工厂方法)?** → 在类内部使用 `companion object`。```kotlinclass ApiClient {companion object {const val BASE_URL = "https://api.example.com"fun newInstance(): ApiClient { ... }}}// 使用:ApiClient.BASE_URL, ApiClient.newInstance()```### 总结| 关键词 | 核心思想 | 类比 | | :--- | :--- | :--- | | **`class`** | **蓝图** | 饼干模具 | | **`object`** | **唯一的实物** | 唯一的、特殊的饼干 | | **`companion object`** | **放在蓝图画旁边的唯一实物** | 和饼干模具放在一起的那个唯一的标准参考饼干 |简单来说:用 `class` 来“批量生产”,用 `object` 来“独一无二”。
