web-dev-qa-db-fra.com

L'égalité à Kotlin

J'apprends Kotlin, avec un arrière-plan C++ et Java. Je m'attendais à ce que les éléments suivants impriment true et non false. Je sais que == correspond à equals. L'implémentation par défaut de equals ne compare-t-elle pas chaque membre, c'est-à-dire firstName et lastName? Si tel est le cas, ne verrait-il pas les valeurs de chaîne comme égales (puisque == correspond à equal encore)? Apparemment, il y a quelque chose lié à l'égalité contre l'identité que je n'ai pas encore bien compris dans Kotlin.

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

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

L'implémentation par défaut equals que vous décrivez n'existe que pour les classes de données. Pas pour les classes régulières où l'implémentation est héritée de Object et rend juste l'objet égal à lui-même.

5
JB Nizet

Égalité référentielle

Java

En Java, l’implémentation par défaut de equals compare la variable référence , qui correspond à ce que == always fait:

La méthode equals pour la classe Object implémente la relation d'équivalence La plus discriminante possible sur les objets; c’est-à-dire que pour toute valeur de référence x et y non nulle, cette méthode retourne true si et seulement si x et y font référence au même objet (x == y a la valeur true).

Nous appelons cela " référentiel égalité". 

Kotlin

Dans Kotlin, == est compilé en equals, alors que === est l'équivalent du == de Java.

Égalité structurelle

Chaque fois que nous voulons plutôt structurelle que référentielle égalité, nous pouvons redéfinir equals, qui est jamais fait par défaut pour les classes normales, suggéré. Dans Kotlin, nous pouvons utiliser data class, pour lequel le compilateur crée automatiquement une implémentation basée sur les propriétés du constructeur (read here ).

N'oubliez pas de toujours surcharger hashCode si vous écrasez equals (et vice versa) manuellement et que vous vous en tenez aux très stricts contrats des deux méthodes. Les implémentations générées par le compilateur de Kotlin satisfont au contrat.

20
s1m0nw1

== pour l'égalité

En Java, vous pouvez utiliser == pour comparer les types de primitive et de référence. Si appliqué aux types primitifs, Java == compare les valeurs, tandis que == sur les types de référence compare les références. Ainsi, à Java, il existe une pratique bien connue consistant à toujours appeler les égaux et un problème bien connu consistant à oublier de le faire.

En Kotlin, == est le moyen par défaut de comparer deux objets: il compare leurs valeurs en appelant égaux sous le capot. Ainsi, si égal est remplacé dans votre classe, vous pouvez comparer ses instances en toute sécurité en utilisant ==. Pour comparer les références, vous pouvez utiliser l'opérateur ===, qui fonctionne exactement de la même manière que == en 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"
}

Dans votre cas, MyPerson est un data class qui génère automatiquement les implémentations de méthodes universelles (toString, equals et hashCode).

2
Chulo