comparaison d'objets

Dj T@lDj T@l Membre
20:42 modifié dans API AppKit #1
Bonjours tout le monde,

Alors j'ai quelque petite question avous poser:

- Comment comparer 2 objets par exemple j'ai une classe category et je veut tester si 2 instances de cette classe, quelle methode utiliser? Doit je implementer la methode : - (BOOL)isEqualTo:(id)object ou y a t'il une autre solution.
- Comment copier un objet : meme exemple avec ma classe category, j'ai une instance de cette classe et je veut la copier, je doit implementer la methode -(id)copy c'est bien ca ou je me trompe?.

Voila j'espere que j'ai été clair (pas sur).
Merci d'avance a vous

Réponses

  • Eddy58Eddy58 Membre
    20:42 modifié #2
    Hello Dj T@l :)

    Pour comparer deux objets, tu peux effectivement utiliser isEqual :
    [tt]
    if ([objet1 isEqualTo:objet2]==YES)
    {
        NSLog(@Objet1=Objet2);
    }
    [/tt]
    Tu peux aussi comparer simplement leurs pointeurs ainsi :
    [tt]
    if (objet1==objet2)
    {
        NSLog(@Objet1=Objet2);
    }
    [/tt]

    Pour la copie, il faut que ta classe supporte le protocole NSCopying, et tu peux ensuite utiliser copy :
    [tt]
    id objet2=[objet1 copy];
    [/tt]
  • Dj T@lDj T@l Membre
    20:42 modifié #3
    est ce que ceci est juste pour une methode copy

    - (id)copy {
    return (BMCategory alloc] init:[self name]:[self color);
    }

    sachant que ma classe est comme ca :

    @interface BMCategory : NSObject {
    NSString *name;
    NSColor *color;
    }
  • avril 2005 modifié #4
    dans 1113940036:

    Hello Dj T@l :)

    Pour comparer deux objets, tu peux effectivement utiliser isEqual :

    Tu peux aussi comparer simplement leurs pointeurs ainsi :


    Attention, quand je voie ça sans que ce soit nuancé, je hurle. Fondamentalement, les deux sont très différents:
    - isEqual envoie -hash (fouf ...couché!) aux 2 objets, cette méthode renvoie un nombre estimé suivant les variables d'instance et si ce nombre est égal pour les deux objets, alors il renvoie YES. Pour un NSNumber, le hash serait par exemple ce nombre.


    -la comparaison de pointeur renvoie YES si les objets pointent vers la même adresse mémoire.

    Ainsi pour:
    [tt]NSString* str1 = [NSString stringWithString:@test];
    NSString* str2 = [NSString stringWithString:@test];[/tt]

    [str1 isEqual:str2] revoie YES;
    str1 == str2 renvoie NO;


    Par contre pour ta copie ton code est mauvais. Si ta classe est immutable, tu peux contenter de renvoyer [self retain]; dans le cas contraire, ce serait plutôt un truc dans le genre:
    [tt]-(id)copy {
        id obj = BMCategory alloc] init];<br />//Si name est immutable:<br />    [obj setName:name]; //tu as qd même accès à  la variable name à  l&#39;intérieur de la classe...<br />//Sinon<br />    [obj setName:[[name copy] autorelease;

        [obj setColor:color];

        return obj;
    }[/tt]

    Alors pourquoi cette distinction immutable et mutable, simplement parce que si name est mutable, le name du nouvel objet sera le même que celui de l'ancien (au sens ==), une modification qui sera faite d'un côté sera donc reportée de l'autre. Par contre si l'objet est immutable, le changement de valeur en créant un nouvel objet et en redéfinissant le pointeur. Chaque instance a son propre pointeur, donc changer l'un n'affecte pas l'autre.
  • Eddy58Eddy58 Membre
    20:42 modifié #5
    dans 1113947716:

    Attention, quand je voie ça sans que ce soit nuancé, je hurle. Fondamentalement, les deux sont très différents:

    Hurles pas trop fort Renaud, il est tard quand même... :P ;)
    En tout cas, merci pour cette précision importante. :)

  • fouffouf Membre
    20:42 modifié #6
    Dommage que je puisse pas faire de l'ordi jusqu'à  minuit, sinon, j'aurais répondu la même chose que Renaud à  ceci près que je n'aurais pas utilisé de -hash.

    Dans ce cas la, on dit:
    GRILLED
  • Dj T@lDj T@l Membre
    20:42 modifié #7
    Cool merci pour les details ca va m'aider.
    Par contre dans le cas que je donne :
    (id)copy {
      return (BMCategory alloc] init:[self name]:[self color);
    }

    [self name] et [self color] ne sont pas des variables mais des methodes (mes accesseur) et il renvoie deja :['variable' copy] autorelease].
    Va falloir que je teste ca ce soir moi. Voir cette histoire de mutable/ immutable (mes objet doivent etre mutable en tout cas).

    En tout cas merci
  • 20:42 modifié #8
    Les objets sont mutables s'il existe des méthodes pour changer le contenu. À titre d'info, les couleurs sont immutables, pour ce qui est des string, il faut se référer au nom de la classe, immutable dans le cas de NSString, mutable dans le cas deNSMutableString.

    Par contre renvoyer [[variable copy] autorelease]; n'est pas malin (mais ce n'est pas faux) pour les objets immutables, car 1. copy ne fait jamais que renvoyer [self retain] et 2. il vaut mieux prendre l'habitude d'éviter d'utiliser l'autorelease pool (il y a des cas où ce n'est pas possible de faire autrement, comme dans le cas de renvoi d'objets mutables), nettement plus gourmande en processeur et mémoire (là  tu peux l'éviter en renvoyant simplement la valeur).
  • Dj T@lDj T@l Membre
    20:42 modifié #9
    Donc en fait il vaut mieux que mes acceseeur renvoie [variable copy].

    Par contre (oui je sait ca fait beaucoup de question)

    Ma classe category, je doit pouvoir la modifier n'importe quand donc elle est mutable si j'ai bien compris c'est ca ?
    ca c'st bon
    @interface BMCategory : NSObject {
      NSString *name;
      NSColor *color;
    }
    je dois pas remplacer ma NSString par une NSMutableString meme si category est mutable ?
    Apres je transaform mes accesseur un
    [variable copy] au lieu de [[variable] copy autorelease]
    de cette maniere est ce que ma methode copy donner auparabvant reste toujours correct.Je precise que mes objets doivent etre independant si je modifie le nom ou la couleur de l'un je veut pas que cela modifier les attribut de l'autre.

    Merci pour tous les conseils (pas toujours evident la gestion memoire en Objective-C)
  • ClicCoolClicCool Membre
    20:42 modifié #10
    dans 1113977761:

    Dans ce cas la, on dit:
    GRILLED



    Plus de 7 heures après c'est plus Grilled mais Carbonised Fouf ;)
  • Dj T@lDj T@l Membre
    avril 2005 modifié #11
    Oups pardon mes accesseurs sont comme ceci :
    - (NSString *)name
    {
        return [[name retain] autorelease];
    }

    J'espere que c'est bon aussi et que du coup ma methode copy est toujours valable ?

    Encore une question
    Quel est la difference entre
    NSString* str1 = [NSString stringWithString:@test];
    et
    NSString* str1 = @test
    je comprend pas tres bien la et quelle forme faut il utiliser ?
  • ChachaChacha Membre
    20:42 modifié #12
    dans 1114009318:

    Oups pardon mes accesseurs sont comme ceci :
    - (NSString *)name
    {
        return [[name retain] autorelease];
    }

    Pourquoi ne pas écrire simplement
    <br />return name;<br />
    



    Quel est la difference entre
    NSString* str1 = [NSString stringWithString:@test];
    et
    NSString* str1 = @test

    La première forme crée un objet temporaire qui sera détruit quand l'autorelease pool se videra.

    +
    Chacha
  • Dj T@lDj T@l Membre
    20:42 modifié #13
    il me semblait avoirlu je sait plus ou qu'il ne fallait pas revoyé la valeur comme ca.
    Mias si c'est le plus ismple et que ca ne crée pas de fuite de memoire je vai fare comme c'est plus rapide a ecrire.
  • 20:42 modifié #14
    Quelques lignes plus haut, je pense ;)
  • Dj T@lDj T@l Membre
    20:42 modifié #15
    Donc en fait quel est la meilleur implementation por un acceseur: renvoyer la varibale ou renvoyer variable retain] autorelase] ou encore autre chose.<br /><br />En plus j&#39;ai un probleme avec ma copie<br />- (void)testCopy {<br /> BMCategory *cat;<br /> BMCategory *cate;<br /> <br /> cat =[[BMCategory alloc] init:@&quot;loisir&quot; :[NSColor redColor;
    cate = [cat copy];
    STAssertTrue([cat isEqualTo:cate], @cat & cat should be equal on color and name);
    STAssertTrue([cat isEqual:cate], @cat & cat should be equal on color and name);
    STAssertFalse([cat isEqual:cate], @cat & cat should be equal on color and name);
    STAssertEqualObjects(cat, cate, @object shoudl be the same);
    [cat release];
    [cate release];
    }

    Sa me dit qu'il y a des erreur lors e l'execution des tes sur 2 lignes:
    /Users/garcera/developement/en cours/Phoenix project/bankmanager/trunk/src/TBMCategory.m:54: error: -[TBMCategory testCopy] : "[cat isEqual:cate]" should be true. cat & cat should be equal on color and name
    /Users/garcera/developement/en cours/Phoenix project/bankmanager/trunk/src/TBMCategory.m:56: error: -[TBMCategory testCopy] : '<BMCategory: 0x371b50>' should be equal to '<BMCategory: 0x371bb0>' object shoudl be the same

    mais je comprend pas pourquoi en gros les objets ne sont pas egaux alors que leur varible oui. Je comprend plus rien.
    Si quelqu'un a une solution ?
  • ChachaChacha Membre
    20:42 modifié #16
    dans 1114014123:

    Donc en fait quel est la meilleur implementation por un acceseur: renvoyer la varibale ou renvoyer [[variable retain] autorelase] ou encore autre chose.

    "[[variable retain] autorelease]", ça ne sert absolument à  rien. La bonne méthode, c'est "return variable;"
    Par contre, après, il faut faire attention à  ce que l'on veut.
    Souvent, on ne veut pas que l'utilisateur de l'accesseur puisse modifier l'objet. Donc il faut faire attention.
    1) Si la variable est immutable (style NSDictionary, NSString, NSArray, NSNumber...) aucun souci
    2) Si la variable est mutable (style NSMutableString, NSMutableArray...), alors il suffit de donner au type de retour de l'accesseur celui de la classe mère non mutable ! exemple:
    <br />@interface Toto<br />{<br />  NSMutableString* name;<br />}<br />-(NSString*) name;<br />@end<br /><br />@implementation Toto<br />-(NSString*) name<br />{<br />  return name;<br />}<br />@end<br />
    

    Il y a un risque toutefois : rien n'empêche l'utilisateur avisé de passer outre cette astuce et d'envoyer malgré tout des messages de la classe mutable à  l'objet non mutable : ça marchera !

    3)Pour ne prendre aucun risque:
    -(NSString*) name
    {
      return [[name mutableCopy] autorelease];
    }

    Mais c'est bien lourdingue et inutile la plupart du temps

    +
    Chacha
  • Dj T@lDj T@l Membre
    20:42 modifié #17
    Ok merci chacha (et les autres aussi) pour touts ces explications.
    J'ai plus qu'a modifié tous mes accesseur (heuresemnt que jai pas fini toute mes classes).
    Bon b'eh maintenant j'ai plus qu'a finir mes test unitaire des classe de base de mon appli (je vous la presenterai des qu'elle sera plus avancé).
  • AntilogAntilog Membre
    20:42 modifié #18
    dans 1114025059:

    Ok merci chacha (et les autres aussi) pour touts ces explications.
    []


    C'est le moment rêvé de se mettre à  accessorizer !
    Cf http://www.objective-cocoa.org/forum/index.php?topic=850.0
  • Dj T@lDj T@l Membre
    20:42 modifié #19
    Ben oui mais justement c'est accessorizer  qui m'a généré mes methodes.
    Donc je voulai verifié si c'etait bon.
    Donc je pense que je vait laissé tel quel pour le moment est si je voit que c'est trop lourd en ressource je me pencherai en detail dessus.
    En tout cas accessorizer est vraiment super il genere pas mal de chose, moi j'aime beaucoup surtout pour toutes les methodes repetitives.
  • AntilogAntilog Membre
    20:42 modifié #20
    Comme tu as du le remarquer, accessorizer te permets de choisir, voir même de modifier de con-t'en-fomble la méthode de génération de tes accesseurs, ce qui te permets de changer un peu (beaucoup) plus facilement après coup.
  • Dj T@lDj T@l Membre
    20:42 modifié #21
    J'ai vu oui que tout est tres configurable mais j'ai pas encore eu le temps de tout regler tres propre.
    En pus je usi pas un pros de l'objective-C donc je me renseigne en meme temps sur les bon reflexe pour evitre les probleme de memoire.
    En tout cas c'est un tres bon soft qui rend de fire service. Merci de nous l'avoir presenter.
Connectez-vous ou Inscrivez-vous pour répondre.