第 6 章 · 类与对象

data class 一行抵 50 行;object 单例零模板;sealed 类型安全分支建模。

📦 data class:1 行 vs 50 行

☕ Java

public class User {
    private final String id;
    private final String name;
    private final int age;

    public User(String id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public String getId() { return id; }
    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age == user.age &&
               Objects.equals(id, user.id) &&
               Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, age);
    }

    @Override
    public String toString() {
        return "User{...}";
    }
}

🟣 Kotlin

data class User(
    val id: String,
    val name: String,
    val age: Int
)

📦 自动生成了什么?

方法说明
equals()结构相等比较
hashCode()基于属性算 hash
toString()"User(id=u001,...)"
copy(...)不可变更新
componentN()解构声明

🛠 data class copy 构建器

实战:用 copy(...) 做"不可变更新" - 函数式编程的核心思想。

data class User(
    val id: String,
    val name: String,
    val age: Int,
    val email: String,
)

原始 user 对象

想"修改"哪些字段?

📝 生成的代码



        

📤 结果

💡 注意:copy 创建的是新对象,原 user 不变。 这就是"不可变更新",避免了状态共享带来的并发 bug。

🎯 object 单例 vs class 实例

Kotlin 的 object 关键字一行实现单例,跟 Java 的"私有构造 + static instance"模式等价但更简洁。

🏭

class

class User(name: String)
val u1 = User("a")
val u2 = User("a")
u1 === u2  // false
// 每次都是新对象
🏛

object

object DB {
    fun query() = ...
}
DB.query()
DB === DB  // true
// 全局唯一的实例
🔌

companion object

class User {
  companion object {
    fun create() = ...
  }
}
User.create()
// 看起来像 static

💡 三个 object 的真实场景

场景用哪个例子
全局单例(DB / Logger / Config)objectobject Logger { fun log(msg: String) }
静态工厂方法 / 常量companion objectUser.create("Alice") / User.MAX_LEN
替代匿名内部类object 表达式val l = object : Listener { ... }

🔐 sealed class:类型安全的"状态机"

常用场景:网络请求结果(Loading / Success / Failure)、UI 状态、ADT 建模。

sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Failure(val error: String) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

fun handle(r: Result<String>) = when (r) {
    is Result.Success -> "✅ ${r.data}"
    is Result.Failure -> "❌ ${r.error}"
    Result.Loading    -> "⏳ 加载中"
    // 不需要 else!编译器知道穷尽了
}

🎮 试试看:选一种状态

Result.Success("Hello") Result.Failure("404") Result.Loading
点上面任意一个状态看 when 表达式怎么处理它

🆚 vs enum

维度enumsealed class
携带数据固定字段每个子类不同结构
子类位置enum 内同文件 / 同模块
when 穷尽支持支持
典型场景固定枚举值(性别、状态码)异质状态(Result / Event / UiState)