Kotlin 中的平等

Equality in Kotlin

我正在学习 Kotlin,具有 C++ 和 Java 背景。我期待以下打印 true,而不是 false。我知道 == 映射到 equalsequals 的默认实现是否不比较每个成员,即 firstNamelastName?如果是这样,它不会将字符串值视为相等(因为 == 再次映射到 equals)吗?显然,我在 Kotlin 中还没有正确理解与平等与身份相关的内容。

class MyPerson(val firstName: String, val lastName: String)

fun main(args: Array<String>) {
   println(MyPerson("Charlie", "Parker") == MyPerson("Charlie", "Parker"))
}

您描述的默认 equals 实现仅适用于数据 类。不适用于从 Any 继承实现的常规 类,只需使对象等于自身即可。

引用平等

Java

在Java中,equals的默认实现比较变量的reference,这就是== always所做的:

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

我们称之为“参考平等”。

Kotlin

在 Kotlin 中 == 被编译为 equals,而 === 相当于 Java 的 ==.

结构平等

每当我们想要结构而不是引用平等时,我们可以覆盖equals,即按照您的建议,normal 类 默认情况下从不 完成。在 Kotlin 中,我们可以使用 data class,编译器会根据构造函数属性自动为其创建一个实现(阅读 here)。

如果您手动覆盖 equals(反之亦然),请记住始终覆盖 hashCode 并坚持非常严格的 contracts两种方法。 Kotlin 的编译器生成的实现确实满足契约。

== for equality

In Java, you can use == to compare primitive and reference types. If applied to primitive types, Java’s == compares values, whereas == on reference types compares references. Thus, in Java, there’s the well-known practice of always calling equals, and there’s the well-known problem of forgetting to do so.

In Kotlin, == is the default way to compare two objects: it compares their values by calling equals under the hood. Thus, if equals is overridden in your class, you can safely compare its instances using ==. For reference comparison, you can use the === operator, which works exactly the same as == in Java.

class MyPerson(val firstName: String, val lastName: String){
    override fun equals(other: Any?): Boolean {
        if (other == null || other !is MyPerson) return false
        return firstName == other.firstName && lastName == other.lastName
    }
}

fun main(args: Array<String>) {
    println(MyPerson("Charlie", "Parker") == MyPerson("Charlie", "Parker")) // print "true"
}

在您的案例中,MyPerson 曾经是一个 data class,它自动生成通用方法(toStringequalshashCode)的实现。