Déclaration anticipée ( @class, @protocol) et importation des fichier.h
Hello,
J'ai lu quelque part ( désolé je ne me souviens pas de la référence /rolleyes.gif' class='bbc_emoticon' alt='::)' /> ) : "Pour éviter des dépendances cycliques des fichiers d'entête il est necessaire de recourir à la déclaration forward des classes ( @class) lorsqu'on a juste besoin de spécifier leur existence et non leur définition".
Mon problème :
"Les dépendances cycliques " ?.
Quand je code, dés fois j'utilise par exemple : @class MyClass; pour dire au compilateur ( et linker) comme quoi MyClass est un nom de class, dans ce cas il va se calmer /clap.gif' class='bbc_emoticon' alt=' ' /> . Mais j'ai tendance ( dés fois) à ne pas mettre @class mais plutôt un #import "MyClass.h", est-ce que je mérite une claque /huh.gif' class='bbc_emoticon' alt='???' /> ?
Autre point, j'ai regardé bien sur dans la documentation Apple à propos de l'utilisation de @class,
"The @class directive minimizes the amount of code seen by the compiler and linker, and is therefore the simplest way to give a forward declaration of a class name. Being simple, it avoids potential problems that may come with importing files that import still other files. For example, if one class declares a statically typed instance variable of another class, and their two interface files import each other, neither class may compile correctly. "
Est-ce que quelqu'un peux m'expliquer la phrase soulignée SVP ?. Un exemple de code sera le bienvenu. Merci
J'ai lu quelque part ( désolé je ne me souviens pas de la référence /rolleyes.gif' class='bbc_emoticon' alt='::)' /> ) : "Pour éviter des dépendances cycliques des fichiers d'entête il est necessaire de recourir à la déclaration forward des classes ( @class) lorsqu'on a juste besoin de spécifier leur existence et non leur définition".
Mon problème :
"Les dépendances cycliques " ?.
Quand je code, dés fois j'utilise par exemple : @class MyClass; pour dire au compilateur ( et linker) comme quoi MyClass est un nom de class, dans ce cas il va se calmer /clap.gif' class='bbc_emoticon' alt=' ' /> . Mais j'ai tendance ( dés fois) à ne pas mettre @class mais plutôt un #import "MyClass.h", est-ce que je mérite une claque /huh.gif' class='bbc_emoticon' alt='???' /> ?
Autre point, j'ai regardé bien sur dans la documentation Apple à propos de l'utilisation de @class,
"The @class directive minimizes the amount of code seen by the compiler and linker, and is therefore the simplest way to give a forward declaration of a class name. Being simple, it avoids potential problems that may come with importing files that import still other files. For example, if one class declares a statically typed instance variable of another class, and their two interface files import each other, neither class may compile correctly. "
Est-ce que quelqu'un peux m'expliquer la phrase soulignée SVP ?. Un exemple de code sera le bienvenu. Merci
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Chacune des classes utilise l'autre, il y a une dépendance cyclique. Dans ce cas il vaut mieux qu'au moins une des deux déclarations de classe utilisée soit en @class plutôt que #import.
En fait ce que j'ai pas compris : que ce que une redondances cyclique peux engendrer comme erreur ?
Il y a un retain cycle car Paul retient Jean et Jean retient Paul
Ca pose problème parce que du coup personne ne lâchera jamais l'autre : Paul va attendre que Jean le lâche pour lâcher Jean lui-même, et Jean va faire de même, au final personne ne cèdera, personne ne lâchera prise, et Jean et Paul ne pourront jamais se libérer (dealloc), donc il y a fuite mémoire car tes objets ne sont jamais détruits.
Si Paul tient le pied de Jean (retain / strong reference), mais que Jean ne fait que regarder Paul du retard (weak reference), alors on évite le "retain cycle" et Paul lâchera le pied de Jean dès que plus personne ne retiendra Paul lui-même. Et comme Jean ne retient pas Paul mais ne fait que le regarder de loin (weak reference) cela ne va pas empêcher Paul de lâcher prise.
Les dépendances cycliques posent un problème logique, que les compilateurs ne savent pas résoudre, il me semble: Classe1 référence Classe2 qui référence Classe1 qui références Classe 2, etc. Tu as donc une boucle de références.
En utilisant le mot clé @class, tu signifies seulement au compilateur qu'il existe une telle classe, mais pas comment elle est faite exactement. Problème résolu!
Je dirais qu'en général, c'est de toute façon une mauvaise idée, parce que tu crées une dépendance forte entre les deux classes. Il est souvent plus intéressant de dire qu'on pointe sur un objet qui se conforme à un protocole, et pas plus.
Au temps pour moi
- ça ne devrait pas poser problème au compilo puisque de base un #import ne peut être inclus qu'une fois, contrairement au #include
- ou alors un problème d'édition de liens, ou de dynamic loader ?
#import fait ça très bien.
@class c'est juste pour dire au compilateur "il y a une classe avec ce nom là , tu n'as pas besoin de savoir de quoi elle est constituée, je te dis juste qu'elle existe". Avantage, ça évite au compilateur d'inclure tout le contenu du .h juste pour compiler alors qu'il n'en a pas besoin d'une part, et ça évite que le compilateur recompile le fichier si le .h a changé (par exemple si on a changé une méthode) alors que le fichier qui l'utilise s'en fiche des méthodes en question.
Par exemple, si dans A.h je veux déclarer une propriété de type B :
Bref, pour moi ces forward declarations c'est pas pour éviter les imports cycliques (ça c'est le rôle de #import, fonctionnalité que n'a pas #include), mais pour réduire les dépendances entre les .h, éviter de faire des unités de compilations trop grosses, et améliorer les temps de compilation.
Et bien sûr, ça sert également si on ne sépare pas dans des headers différents les classes ou protocoles A et B (cas courant du "@protocol TotoDelegate" qui déclare des méthodes genre "-(void)toto:(Toto*)toto didTellJoke:(NSString*)joke", mais qui est déclaré dans le même Toto.h, avant la déclaration de la classe Toto elle-même... )