首页 文章

科特林的平等

提问于
浏览
7

我正在学习Kotlin,具有C和Java背景 . 我期待以下打印 true ,而不是 false . 我知道 == 映射到 equals . equals 的默认实现是否不比较每个成员,即 firstNamelastName ?如果是这样,它不会看到字符串值相等(因为 == 再次映射到 equal )?显然,在Kotlin还没有找到合适的地方 .

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

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

3 回答

  • 2

    您描述的默认 equals 实现仅适用于数据类 . 不适用于从 Object 继承实现的常规类,只是使对象等于它自己 .

  • 5

    参考平等

    Java

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

    类Object的equals方法实现了对象上最具辨别力的等价关系;也就是说,对于任何非空引用值x和y,当且仅当x和y引用同一对象时,此方法才返回true(x == y的值为true) .

    我们称之为“ referential 平等” .

    Kotlin

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

    结构平等

    每当我们想要相当于结构而不是引用相等时,我们可以覆盖 equals ,正如你所建议的那样,默认情况下这对于普通类是永远不会完成的 . 在Kotlin中,我们可以使用 data class ,编译器会根据构造函数属性自动创建一个实现(读here) .

    如果您覆盖 equals (反之亦然) manually ,请记住始终覆盖 hashCode 并坚持使用两种方法的非常严格的contracts . Kotlin的编译器生成的实现确实满足了 Contract .

  • 20

    == for equality在Java中,您可以使用==来比较原语和引用类型 . 如果应用于基本类型,则Java ==比较值,而引用类型上的==比较引用 . 因此,在Java中,有一种众所周知的总是调用equals的做法,并且存在众所周知的忘记这样做的问题 . 在Kotlin中,==是比较两个对象的默认方式:它通过在引擎盖下调用equals来比较它们的值 . 因此,如果在类中重写了equals,则可以使用==安全地比较其实例 . 为了参考比较,您可以使用===运算符,它与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 ) .

相关问题