问题的历史:
在 Kotlin 1.9 之前,object 对象不能是数据对象 — 你不能拥有一个单例,自动获取 equals, hashCode, toString 方法,就像数据类那样。随着 data object 的出现,这一限制被取消了。现在可以创建一个带有自动生成方法的单例对象,适用于值和类枚举样式的模式。
问题:
以前,为了获得正确的 equals(), hashCode(), toString(),即使是单例对象,也需要手动实现它们或使用其他技巧,这增加了冗余代码和出错的可能性。
解决方案:
使用 data object 来表示那些实例唯一的对象,同时需要标准的 equals/hashCode/toString 行为,以便于在集合中传递、序列化、比较和调试。
代码示例:
data object NotAvailable fun checkStatus(status: Any) = when (status) { NotAvailable -> "数据缺失" else -> "其他状态" } val set = setOf(NotAvailable) println(NotAvailable in set) // true println(NotAvailable.toString()) // NotAvailable
关键特性:
data object 可以包含属性吗?
可以,但只能是没有 backing field 的 val 属性(因为单例不应存储任何东西)
data object Loading { val status: String get() = "加载中..." }
从 equals 的角度看,data object 与普通的 object 有什么不同?
普通对象的 equals 只检查引用相等性,而 data object 则比较数据契约,但在单例情况下,这永远是同一个对象。然而,重写的 equals/hashCode 对于集合来说更有用。
可以从 data object 继承吗?
不可以,data object 是最终的,就像 Kotlin 中的任何对象一样 — 不能继承。
为了所有状态使用不同的 data object,而不是 enum。经过一年,需求串行化成字符串,需要手动将对象名称与类型进行匹配。
优点:
缺点:
对于网络请求的返回值,使用 data object 表示特定状态:Loading、Empty、Error。这样代码紧凑,支持 equals, hashCode, toString 自动。
优点:
缺点: