简体   繁体   English

Kotlin 密封类和哈希码/等于

[英]Kotlin sealed classes and hashcode/equals

I'm seeing writing a test that I cannot assert two sealed classes with same "subclass" and same value under the hood are equal.我正在编写一个测试,我无法断言两个具有相同“子类”和相同值的密封类在后台是相等的。 They are distinct.他们是不同的。

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()
        }
    }
}

This main function returns:这个主要的 function 返回:

false
true

I do not really get why that behaviour.. I guess it is related to the nature of sealed classes it self and I'm not getting it?我真的不明白为什么会出现这种行为。我想这与密封类本身的性质有关,但我不明白?

Thanks in advance提前致谢

Kotlin Sealed classes do not override the default equals() implementation from the Object Java class. This means that the objects are compared using their reference, hence a1 and a2 are not equal. Kotlin 密封类不会覆盖Object Java class 中的默认equals()实现。这意味着对象是使用它们的引用进行比较的,因此a1a2不相等。

Kotlin Data classes in their turn do override the equals() method based on all properties declared in the primary constructor (read more about them at https://kotlinlang.org/docs/data-classes.html ). Kotlin 数据类会根据主构造函数中声明的所有属性依次覆盖equals()方法(在https://kotlinlang.org/docs/data-classes.html阅读更多相关信息)。

That's normal behaviour for any class - two different instances are not equal by default, because it checks for referential equality (ie the two references are pointing at the same object in memory).这是任何 class 的正常行为 - 默认情况下两个不同的实例不相等,因为它检查引用相等性(即两个引用指向内存中的相同 object)。

class NormalClass(val value: String)

val a = NormalClass("foo")
val b = NormalClass("foo")
println(a == b)

> false

data class es provide a default equals and hashCode implementation that ignores referential equality, and just compares the object type, and the values of the properties in the constructor data class es提供了一个默认的equalshashCode实现,忽略引用相等,只是比较object类型,和构造函数中属性的值

data class DataClass(val value: String)

val a = DataClass("foo")
val b = DataClass("foo")
println(a == b)

> true

A sealed class is really just a special type that a class can belong to, which is mostly used for things like defining all the possible objects that have that type. sealed class实际上只是 class 可以属于的一种特殊类型,它主要用于定义所有可能具有该类型的对象。 It allows you to group disparate classes and objects together, and do things like exhaustive pattern matching (eg a when clause operating on a MySealed object can tell when you've checked all the possible members of that type)它允许您将不同的类和对象组合在一起,并执行诸如详尽模式匹配之类的操作(例如,在MySealed object 上运行的when子句可以告诉您何时检查了该类型的所有可能成员)

Your A class is a normal class, so two instances of it are not equal by default.A class 是一个普通的 class,因此默认情况下它的两个实例不相等。 If you made it an object in MySealed , there would only be one instance of it.如果您在object中将其设置为MySealed ,那么它只会有一个实例。 In that sense, it can operate a little like an enum class .从这个意义上说,它的操作有点像enum class A sealed class lets you mix and match these different types, with some benefits and drawbacks密封的 class 让您可以混合搭配这些不同的类型,有一些优点和缺点

You can just make A a data class inside the sealed class, if you want them to match if they have the same value , but also be a MySealed你可以在密封的class里面做A数据class,如果你想让它们匹配如果它们有相同的value ,也可以是一个MySealed

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM