编程后端开发工程师

解释 Kotlin 中数据类(data classes)、普通类和继承类之间的区别。在什么情况下应该使用数据类,编译器施加了哪些限制?

用 Hintsage AI 助手通过面试

答案

在 Kotlin 中,data class 用于存储数据。编译器会自动生成方法 equals()hashCode()toString(),以及函数 copy()componentN(),这大大简化了对这些对象的操作:

data class User(val name: String, val age: Int) val u1 = User("Ivan", 30) val u2 = u1.copy(age = 31)

普通类没有这样的自动生成方法;一切都需要手动编写。数据类更适合用于 DTO、模型和数据结构。

数据类的限制:

  • 主构造函数必须至少包含一个参数。
  • 所有构造函数参数必须标记为 valvar
  • 数据类不能是 abstractopensealedinner
  • 不建议将数据类用于具有业务逻辑或继承结构的类。

具有陷阱的问题

"可以声明一个继承自其他数据类的数据类吗?为什么(或为什么不可以)?"

不可以,不能直接将一个数据类继承自另一个数据类。数据类只能继承自接口或普通类(不是数据类)。这是为了防止与自动生成的方法产生混淆(例如,复制继承的属性并不明显)。

data class Base(val id: Int) data class Child(val name: String) : Base(1) // 编译错误:不允许

由于对主题细节不了解而导致的实际错误示例


故事

在一个银行项目中,使用了具有业务逻辑和继承的数据类。添加新字段后,无法正确复制对象,部分业务逻辑丢失(方法未被继承),导致佣金计算错误。


故事

在一个电子商务平台中,数据类用于存储用户购物车的状态。通过 copy() 更新状态后,忘记了内部列表并不会深度复制。由于这个原因,在用户会话之间发生了数据“泄漏”。


故事

在一个集成外部 API 的项目中,将数据类序列化为 JSON 导致出现具有私有可见性的字段,这违反了 API 合同并导致客户端错误。