Kotlin 密封了 类 和 hashcode/equals
Kotlin sealed classes and hashcode/equals
我正在编写一个测试,我无法断言两个具有相同“子类”和相同值的密封 类 是相等的。它们是不同的。
fun main() {
val a1 = MySealed.A("foo")
val a2 = MySealed.A("foo")
System.out.println(a1 == a2)
val a3 = MySealedWithEqualsAndHashCodeOverriden.A("foo")
val a4 = MySealedWithEqualsAndHashCodeOverriden.A("foo")
System.out.println(a3 == a4)
}
sealed class MySealed(val value: String) {
class A(value: String) : MySealed(value)
}
sealed class MySealedWithEqualsAndHashCodeOverriden(val value: String) {
class A(value: String) : MySealedWithEqualsAndHashCodeOverriden(value) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
return true
}
override fun hashCode(): Int {
return javaClass.hashCode()
}
}
}
这个主要函数returns:
false
true
我真的不明白为什么会出现这种行为。我想这与密封的性质有关 类 它本身而我不明白?
提前致谢
Kotlin Sealed classes 不会覆盖 Object
Java class 中的默认 equals()
实现。这意味着使用对象的引用来比较对象,因此 a1
和 a2
不相等。
Kotlin Data classes 会根据主构造函数中声明的所有属性重写 equals()
方法(在 https://kotlinlang.org/docs/data-classes.html 阅读更多关于它们的信息)。
这是任何 class 的正常行为 - 默认情况下两个不同的实例不相等,因为它检查引用相等性(即两个引用指向内存中的同一个对象)。
class NormalClass(val value: String)
val a = NormalClass("foo")
val b = NormalClass("foo")
println(a == b)
> false
data class
es提供了默认的equals
和hashCode
实现,忽略引用相等,只比较对象类型,构造函数中的属性值
data class DataClass(val value: String)
val a = DataClass("foo")
val b = DataClass("foo")
println(a == b)
> true
A sealed class
实际上只是一个特殊的 type 可以属于 class,主要用于定义所有可能的对象有那种类型。它允许您将不同的 classes 和对象组合在一起,并执行诸如详尽模式匹配之类的操作(例如,在 MySealed
对象上运行的 when
子句可以告诉您何时检查了所有该类型的可能成员)
你的A
class是一个普通的class,所以它的两个实例在默认情况下是不相等的。如果您将它设为 MySealed
中的 object
,那么它只会有一个实例。从这个意义上说,它的运作有点像 enum class
。密封的 class 让您可以混合搭配这些不同的类型,有一些优点和缺点
你可以只做A
一个数据class在密封的class里面,如果你想让它们匹配如果它们有相同的value
,也可以一个 MySealed
我正在编写一个测试,我无法断言两个具有相同“子类”和相同值的密封 类 是相等的。它们是不同的。
fun main() {
val a1 = MySealed.A("foo")
val a2 = MySealed.A("foo")
System.out.println(a1 == a2)
val a3 = MySealedWithEqualsAndHashCodeOverriden.A("foo")
val a4 = MySealedWithEqualsAndHashCodeOverriden.A("foo")
System.out.println(a3 == a4)
}
sealed class MySealed(val value: String) {
class A(value: String) : MySealed(value)
}
sealed class MySealedWithEqualsAndHashCodeOverriden(val value: String) {
class A(value: String) : MySealedWithEqualsAndHashCodeOverriden(value) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
return true
}
override fun hashCode(): Int {
return javaClass.hashCode()
}
}
}
这个主要函数returns:
false
true
我真的不明白为什么会出现这种行为。我想这与密封的性质有关 类 它本身而我不明白?
提前致谢
Kotlin Sealed classes 不会覆盖 Object
Java class 中的默认 equals()
实现。这意味着使用对象的引用来比较对象,因此 a1
和 a2
不相等。
Kotlin Data classes 会根据主构造函数中声明的所有属性重写 equals()
方法(在 https://kotlinlang.org/docs/data-classes.html 阅读更多关于它们的信息)。
这是任何 class 的正常行为 - 默认情况下两个不同的实例不相等,因为它检查引用相等性(即两个引用指向内存中的同一个对象)。
class NormalClass(val value: String)
val a = NormalClass("foo")
val b = NormalClass("foo")
println(a == b)
> false
data class
es提供了默认的equals
和hashCode
实现,忽略引用相等,只比较对象类型,构造函数中的属性值
data class DataClass(val value: String)
val a = DataClass("foo")
val b = DataClass("foo")
println(a == b)
> true
A sealed class
实际上只是一个特殊的 type 可以属于 class,主要用于定义所有可能的对象有那种类型。它允许您将不同的 classes 和对象组合在一起,并执行诸如详尽模式匹配之类的操作(例如,在 MySealed
对象上运行的 when
子句可以告诉您何时检查了所有该类型的可能成员)
你的A
class是一个普通的class,所以它的两个实例在默认情况下是不相等的。如果您将它设为 MySealed
中的 object
,那么它只会有一个实例。从这个意义上说,它的运作有点像 enum class
。密封的 class 让您可以混合搭配这些不同的类型,有一些优点和缺点
你可以只做A
一个数据class在密封的class里面,如果你想让它们匹配如果它们有相同的value
,也可以一个 MySealed