Quel est le NSObject isEqual: et la fonction de hachage par défaut?
-
12-09-2019 - |
Question
J'ai une classe de modèle de base de données est un NSObject
. J'ai un ensemble de ces objets dans un NSMutableArray
. J'utilise indexOfObject:
pour trouver un match. Le problème est les changements d'adresse mémoire de l'objet modèle. Je suis donc redéfinissant la méthode hash
pour retourner l'ID de ligne du modèle. Cela ne fixe pas. Je dois aussi substituer la méthode isEqual:
pour comparer la valeur de la méthode de hash
.
Qu'est-ce que l'utilisation de la méthode de isEqual:
pour déterminer l'égalité par défaut?
Je suppose qu'il utilise l'adresse de mémoire. Après avoir lu le la documentation de isEqual:
je pensais qu'il utilise la valeur de la méthode hash
. De toute évidence, ce n'est pas le cas comme ma tentative de passer outre cette valeur n'a pas résolu mon problème initial.
La solution
Comme vous l'avez deviné correctement, le comportement par défaut de NSObject
isEqual:
compare l'adresse mémoire de l'objet. Étrangement, ce n'est pas actuellement documentée dans le Référence de la classe NSObject , mais il est documenté dans le la documentation Introspection, qui stipule que:
Le
NSObject
par défaut de mise en œuvreisEqual:
vérifie simplement pour l'égalité de pointeur.
Bien sûr, comme vous le savez sans doute, sous-classes de NSObject
peuvent passer outre isEqual:
à se comporter différemment. Par exemple, la méthode de NSString
de isEqual:
, lorsqu'il est passé une autre NSString
, d'abord vérifier l'adresse, puis vérifier une correspondance exacte entre littérale les chaînes.
Autres conseils
La réponse au sujet de la mise en œuvre par défaut de isEqual:
est un complet. Donc, je viens d'ajouter ma note sur la mise en œuvre par défaut de hash
. Ici, il est:
-(unsigned)hash {return (unsigned)self;}
i.e. il est juste la même valeur de pointeur qui est utilisé dans isEqual:
. Voici comment vous pouvez vérifier cela:
NSObject *obj = [[NSObject alloc] init];
NSLog(@"obj: %@",obj);
NSLog(@"hash: %x",obj.hash);
Le résultat sera quelque chose comme ceci:
obj: <NSObject: 0x16d44010>
hash: 16d44010
Cordialement.
BTW dans iOS 8 hash
est devenu une propriété pas une méthode, mais il est là.
Je suppose que NSObject
isEquals
utilise l'opérateur ==
et hash
utilise l'adresse mémoire.
méthode isEquals
ne doit jamais utilise hash
comme critère absolu pour l'égalité. Il est garanti d'avoir deux objets ayant hashCode
même, si vous recherchez des objets assez (il suffit de créer plus de 2 ^ 32 objets différents, et au moins deux d'entre eux aura la même hash
).
En d'autres termes, hash
nécessite la spécification suivante: Si deux objets sont égaux, leur hash
doit être égale; Cependant, si deux objets de valeurs de hash
sont égaux, ils ne sont pas nécessairement égaux.
En tant que conseil, vous devriez toujours passer outre isEquals
et hashCode
ensemble.