Différence entre @class et #import

GreensourceGreensource Membre
08:23 modifié dans API AppKit #1
Bonjour! Petite question, quelqu'un saurais me dire la différence qu'il y a entre la directive @class et #import?
J'avoue ne pas bien saisir les subtilités.
Merci,
Pierre

ps:Comment faire pour rechercher sur le forum "@class"; et "#import"? A chaque fois il me renvois tous les sujets ou il voit "class" et "import" du coup il y a un nombre de résultat de malade!

Réponses

  • schlumschlum Membre
    08:23 modifié #2
    @class ne sert qu'à  déclarer que la classe existe...

    #import charge tout le header


    On utilise en général @class en cas de références croisées (pointeur/argument vers un objet A dans un objet B et pointeur/argument vers un objet B dans un objet A)

    à‰quivalent à  "class A;" en C++
  • GreensourceGreensource Membre
    08:23 modifié #3
    Et alors du coup @class est plus léger que l'import? Il vaut mieux privilégier cette méthode? Le but est-il vraiment le même?
    Merci
  • schlumschlum Membre
    08:23 modifié #4
    dans 1235120726:

    Et alors du coup @class est plus léger que l'import? Il vaut mieux privilégier cette méthode? Le but est-il vraiment le même?
    Merci


    Non, c'est pas plus léger parce qu'en général, quand on met @class dans le .h, il faut faire #import dans le .m
  • AliGatorAliGator Membre, Modérateur
    08:23 modifié #5
    En fait quand tu n'as besoin que de savoir que la classe existe mais pas de l'utiliser, c'est une bonne chose d'utiliser @class.

    Exemple, dans une classe Plouf, si dans le .h tu as une variable d'instance de type [tt]Toto* monToto[/tt], comme dans le .h tu ne fais que déclarer la variable mais qu'il n'a pas besoin de savoir quelles sont les méthodes auxquelles la classe Toto sait répondre, un @class suffit.
    Par contre dans le ".m" tu vas sûrement faire des [tt][monToto faitTruc][/tt] et là  il faut qu'il sache que Toto répond (ou pas) à  "faitTruc". Donc là  il faut que tu importes "Toto.h" pour qu'il sache quelles méthodes sont déclarées dedans.

    Après, en pratique on aura du coup quasiment toujours besoin de faire un #import "Toto.h" au moins dans "Plouf.m" pour pouvoir utiliser les méthodes de notre variable d'instance Toto dedans... Donc plutôt que de mettre @class dans le ".h" et #import dans le .m (ce qui serait somme toute une bonne pratique en fait mais bon), on met directement #import dans le .h et on s'embête pas :P
    D'autant que parfois dans "Toto.h" il peut y avoir d'autres trucs utiles, je pense en particulier à  des déclarations de @protocol utiles pour les delegate (si la classe Toto a une variable d'instance [tt]id<TotoDelegate> delegate[/tt] par exemple, moi je déclare le [tt]@protocol TotoDelegate[/tt] au début de Toto.h pour tout regrouper...)

    Au final comme le dit schlum, le cas où l'on est obligé d'utiliser @class c'est dans le cas de références croisées, une classe A qui contient une variable d'instance de type B et cette classe B qui contient elle-même une variable d'instance de A... Si on met des #import partout, pour compiler A il va #importer A.h, qui devoir #importer B.h... qui lui va #importer A.h... et on s'en sortirait pas, d'où le @class qui ne fait que dire au compilo "je te dis juste que la classe B existe".
  • schlumschlum Membre
    février 2009 modifié #6
    En fait c'est même pas un problème de boucle infinie, parce que #import fait en sorte que les fichiers ne soient importés qu'une seule fois (contrairement à  #include).

    Mais si A.h importe B.h et B.h importe A.h, on aura au pre-processing d'un .m qui importe A.h :

    Test.m :
    #import &lt;A.h&gt;<br /><br />// ... (contenu du Test.m)
    


    ->
    #import &lt;B.h&gt;<br /><br />// ... (contenu de A.h)<br /><br />// ... (contenu du Test.m)
    


    ->
    // #import &lt;A.h&gt; (ignoré car déjà  inclus)<br /><br />// ... (contenu de B.h)<br /><br />// ... (contenu de A.h)<br /><br />// ... (contenu du Test.m)
    


    Et il va se plaindre dans le contenu de B.h qu'il y a un truc (à  propos de A) qu'il ne connaà®t pas.


    Si on a un @class au lieu du #import :
    @class A<br /><br />// ... (contenu de B.h)<br /><br />// ... (contenu de A.h)<br /><br />// ... (contenu du Test.m)
    


    -> OK
  • GreensourceGreensource Membre
    08:23 modifié #7
    Okay! Merci beaucoup je comprend beaucoup mieux maintenant!
    J'ai pas bien saisi le coup des delegate encore mais c'est par ce que je ne me suis pas encore penché dessus. Les protocols ça commence à  venir aussi  ;)

    Bon en tout cas merci à  tous, zète bien sympa sur ce forum, et super réactif! Si j'arrive à  faire quelques choses de mes dix doigts ça sera bien grâce à  vous! :adios!:
  • laurrislaurris Membre
    08:23 modifié #8
    dans 1235135355:

    ... mais qu'il n'a pas besoin de savoir quelles sont les méthodes auxquelles la classe Toto sait répondre, un @class suffit.


    A ce propos, j'ai remarqué qu'un @class ne suffit pas quand on veut utiliser les propriétés + @synthetize. Dans ce cas, il faut importer tout le header: je trouve que ça casse largement l'intérêt de @class sous  objective-c 2.
  • Philippe49Philippe49 Membre
    février 2009 modifié #9
    Personnellement, je mets toujours @class dans les .h et #import dans le .m, pour les classes persos évidemment.
    Cela m'évite le casse-tête des références croisées éventuelles, et correspond aux besoins lors de la compilation, sous réserve naturellement que les fichiers .h ne soient pas multiples en terme de contenu.
  • GreensourceGreensource Membre
    08:23 modifié #10
    dans 1235144207:

    Personnellement, je mets toujours @class dans les .h et #import dans le .m, pour les classes persos évidemment.


    Je crois que je vais aussi adopter cette méthode. Ca semble être adapter à  beaucoup de situation.
  • AliGatorAliGator Membre, Modérateur
    08:23 modifié #11
    Bah je te le conseille vivement.
    Philippe en a pris l'habitude apparemment, et c'est une bonne chose, moi c'est pas encore une habitude mais comme je disais pour moi c'est pourtant la façon idéale de faire je pense. Comme ça t'es sûr de pas avoir de surprises...

    Et en plus c'est mieux du côté des dépendances (et donc optimise la compilation avec le makefile qu'utilise Xcode sous le capot quand tu compiles), puisque si dans A.h tu importes "B.h" puis tu compiles... ben si à  un moment tu modifies B.h et recompiles... ben il va recompiler A.h aussi et donc tous les fichiers qui l'importent... puisque le "B.h" sera inclus dans chacun ! Alors qu'avec un @class qui dit juste "je te dis que la classe B existe", bah même si tu rajoutes des méthodes à  ton B.h (mais que tu n'utilises pas ces nouvelles méthodes dans tous tes fichiers qui importent B.h) ça va pas tout recompiler mais que le stricte nécessaire ;)
  • GreensourceGreensource Membre
    08:23 modifié #12
    Ah oui je n'avais pas pensé à  ça. Une autre raison pour utiliser cette méthode! ;)
Connectez-vous ou Inscrivez-vous pour répondre.