编程Kotlin开发者,Android开发者

在Kotlin中,什么是数据对象,如何使用它,以及它与普通对象和数据类有什么区别?

用 Hintsage AI 助手通过面试

答案。

数据对象是Kotlin中的一种新类型声明(从1.9版本开始),它结合了单例对象和数据类的属性。它旨在处理仅希望有一个对象实例并自动生成equals、hashCode、toString方法的情况(如数据类)。

问题的背景

之前,对于存储具有自动生成的toString()和equals()方法的唯一实体,开发人员不得不手动编写对象(object)或折中使用只有一个对象(而不是实例)的数据类。

问题

单例对象(object)没有自动生成的equals、hashCode、toString,而数据类则假设有多个实例,这不适合穷举性的枚举类模型。

解决方案

随着数据对象的出现,两个任务得到了简洁的解决:

  • 类只能是一个实例(单例)。
  • 编译器生成所需的多种方法。

代码示例:

data object LoadingState data object NoData println(LoadingState == LoadingState) // true println(LoadingState.toString()) // LoadingState

主要特点:

  • 始终是单例 — 不能创建第二个实例。
  • 编译器添加了与数据类相同的equals、hashCode、toString方法。
  • 特别方便与密封接口(sealed interface)一起使用,以模拟状态。

有陷阱的问题。

数据对象与普通对象有什么区别?

只有数据对象在编译器级别获得equals、hashCode、toString方法的自动生成;普通对象使用来自Any的实现(引用相等,简陋的toString)。

可以创建带构造参数的数据对象吗?

不可以,数据对象不能有带参数的构造函数。它始终没有参数,因为只存在一个实例。

可以继承数据对象吗?

可以,数据对象可以实现接口,包括密封接口,并成为状态层次结构的一部分。

示例:

sealed interface Result data object Success : Result data object Failure : Result

常见错误和反模式

  • 尝试在数据对象中添加构造参数字段(这是禁止的)。
  • 在仅假定单一实例的情况下使用数据类。

生活中的例子

消极案例

开发人员将“没有数据”建模为对象 NoData,然后通过equals()与外部对象进行比较,得到意外结果(引用查看,而非内容比较)。

优点:

  • 声明简单。

缺点:

  • 在equals/toString时行为不当。

积极案例

使用数据对象表示加载状态,等式和打印遵循预期的数据类规则。模型层可靠地使用状态的模式匹配。

优点:

  • 正确生成多种方法。
  • 安全比较和诊断。

缺点:

  • 数据对象仅在Kotlin的新版本中出现 — 有与旧项目不兼容的风险。