2010-03-29 3 views
2

J'ai un ensemble de classes pour représenter certains objets chargés à partir d'une base de données. Il y a quelques variations de ces objets, donc j'ai une classe de base commune et deux sous-classes pour représenter les différences. L'un des champs clés qu'ils ont en commun est un champ d'identification.Est-ce une méthode de hachage sûre/valide?

Malheureusement, l'identifiant d'un objet n'est pas unique dans toutes les variantes, mais dans une seule variation. Ce que je veux dire, c'est qu'un seul objet de type A pourrait avoir un identifiant compris, disons, entre 0 et 1 000 000. Un objet de type B peut avoir un identifiant compris entre 25 000 et 1 025 000. Cela signifie qu'il y a un certain chevauchement des numéros d'identification. Les objets ne sont que des variations du même genre de chose, alors je veux les considérer comme tels dans mon code. (Ils ont été assignés ids de jeux différents pour des raisons historiques.)

J'ai donc des classes comme ceci:

@class BaseClass 
@class TypeAClass : BaseClass 
@class TypeBClass : BaseClass 

BaseClass a une méthode (NSNumber *) objectId. Cependant, les instances de TypeA et de TypeB peuvent avoir des identifiants qui se chevauchent comme indiqué ci-dessus, donc quand il s'agit d'égalité et de les mettre dans des ensembles, je ne peux pas simplement utiliser l'ID seul pour le vérifier.

La clé unique de ces instances est essentiellement (class + objectId). Donc, je pensais que je pouvais le faire en faisant la fonction de hachage suivante sur le BaseClass:

-(NSUInteger)hash 
{ 
    return (NSUInteger)[self class]^[self.objectId hash]; 
} 

J'ai aussi mis en œuvre isEqual comme ceci:

- (BOOL)isEqual:(id)object 
{ 
    return (self == object) || ([object class] == [self class] && [self.objectId isEqual:[object objectId]]); 
} 

Cela semble fonctionner, mais je suppose que je Je demande juste ici de m'assurer que je ne néglige pas quelque chose - surtout avec la génération du hash en utilisant le pointeur de classe de cette façon. Est-ce sécuritaire ou existe-t-il une meilleure façon de le faire?

+0

Si vous êtes curieux, voici un lien qui explique comment le hachage est utilisé dans Cocoa avec une inclinaison sur les performances. http://www.mulle-kybernetik.com/artikel/Optimization/opti-7.html – codewarrior

Répondre

2

Ceci est probablement sans danger, mais pas nécessairement. En fonction d'une identité de classe stricte, vous risquez de vous mordre si vous vous retrouvez avec une sous-classe (par exemple si KVO fait passer votre classe à une autre *). Il serait probablement un peu plus sûr si vous utilisez une sorte d'ID de classe explicite.

Gardez également à l'esprit que les objets inégaux n'ont pas besoin de hashes différents. La seule exigence est que les objets égaux doivent avoir le même hachage. Donc c'est OK si les objets dans les deux classes ont le même hash tant que cela ne finit pas trop ralentir vos tables de hachage.

(* Honnêtement, je ne me souviens pas du haut de ma tête si la sous-classe secrète KVO se fait passer pour la classe parente, auquel cas vous seriez toujours en sécurité ici, mais j'essaie généralement d'éviter l'identité de la classe

+0

Ah - donc, il suffit de retourner la même chose si isEqual est YES. Cela a du sens et est plus facile que je ne le pensais. Donc je peux juste retourner le hash de l'objectId seul. (Il y a des chevauchements d'identité, mais en pratique ce n'est pas commun - juste quelque chose que je voulais m'assurer ne causerait pas de problèmes.) Je n'ai pas encore trouvé de réponse à la question de savoir comment KVO affecte tout cela. utiliser isKindOf: plutôt que de comparer les classes directement avec ==. Merci! – Sean

Questions connexes