IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

[Delphi 2005][Delphi 6] reference d'unité circulaire


Sujet :

Langage Delphi

  1. #1
    Membre à l'essai
    Inscrit en
    Mars 2005
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 33
    Points : 20
    Points
    20
    Par défaut [Delphi 2005][Delphi 6] reference d'unité circulaire
    Bonjour,

    J'ai un problème de références circulaires.

    Les solutions trouvées dans les livres, la FAQ et le forum ne conviennent pas dans ce cas. Peut-etre que quelqu un a une solution a mon probleme ?

    Mon probleme est le suivant :
    2 unités (ClassX.pas et ClassY.pas) . Dans chacune des unités, une classe est définie : l'unité ClassX.pas contient la classe TClassX et l'unité ClassY.pas contient la classe TClassY. La classe TClassX contient une référence sur un objet de type TClassX et La classe TClassY contient une référence sur un objet de type TClassX. (ci-dessous le code)

    Mes deux classes doivent etre dans des unites separees.

    Etant donné que la définition des classes contient une reference d'objet de l'autre classe, je suis obligé de mettre une instruction "uses" dans la partie "interface" de chacune des unités (sinon, j ai une erreur de compilation). Si je met un "uses" dans les parties interface, j ai un probleme de compilation de type "référence circulaire d'unité".

    La solution classiquement proposée est de mettre le "uses" dans la partie implementation. Mais, cela ne marche pas puisque chaque classe contient une reference sur l autre classe.

    Si je met la declaration de l'une des classe dans la partie implementation, elle ne peut plus etre utilisee par l autre classe.

    Il me reste encore la solution (solution pas encore testee) de faire une unite rassemblant toutes les interfaces de mes classes, et de faire
    une unite par implementation. Mais, je prefere eviter cette solution.

    Quelqu'un aurait-il, stp, une idee pour resoudre ce probleme ?

    Ludo

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    unit ClassX;
     
    interface
     
    uses Contnrs,StdCtrls,SysUtils,ClassY;
     
    type
     
        TClassX = class
        private
           TY : TClassY;
        end;
     
    implementation
    ...
    end.
    -------------------------------------------------------------------------------------
    unit ClassY;
     
    interface
     
    uses Contnrs,StdCtrls,SysUtils,ClassX;
     
    type
        TClassY = class
        private
           TX : TClassX;
     
    implementation
     ...
    end.
    ______________________________
    Balise Code rajouté par yobenzen

  2. #2
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    La seule solution est en effet de placer tes deux classes dans la même unité, en oubliant pas de faire une déclaration forward :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    unit NomUnite;
     
    type
      TClassY = class;
     
      TClassX = class;
        TY : TClassY;
      end;
     
      TClassY = class
        TX : TClassX;
      end;
    N'oublie pas le bouton
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  3. #3
    Membre à l'essai
    Inscrit en
    Mars 2005
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 33
    Points : 20
    Points
    20
    Par défaut
    Merci.

    C est bien ce que je pensais : il n y a pas d autre solution alors. C est dommage parce que je prefere eviter cette solution.

    Je laisse le message encore un peu, histoire de voir si quelqu un a une autre solution.

    Ludo

  4. #4
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut
    Salut
    si tu tiens vraiment à avoir les sources séparées, tu peux essayer comme ça:
    - Crée une unité dans laquelle tu as ton premier objet sans le membre vers l'autre objet.
    - Crée une unité dans laquelle tu mets l'autre
    - Crée une dernière unité dans laquelle tu crées 2 objets qui dérivent de chacun auxquels tu ajoutes le membre...
    Evidemment, si tu te sers beaucoup de ce membre dans le code, ça n'a pas d'intérêt... Et ça t'ajoute un fichier...
    Et puis je ne vois pas en quoi ça dérange de mettre tout dans une seule unité. Tu vas plus t'emm... qu'autre chose ...
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

  5. #5
    Modérateur
    Avatar de Rayek
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    5 235
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 235
    Points : 8 504
    Points
    8 504
    Par défaut
    [Edit] : Avais pas vu que chacune s'appelle ...
    Modérateur Delphi

    Le guide du bon forumeur :
    __________
    Rayek World : Youtube Facebook

  6. #6
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Points : 1 608
    Points
    1 608
    Par défaut
    Tu peux peut être ruser en groupant dans le même fichiers des classes abstraites, et en créant des descendant qui implémentent les fonctions publiées dans les deux fichiers (donc là, séparément...)
    "It's more fun to compute !"

  7. #7
    Membre à l'essai
    Inscrit en
    Mars 2005
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 33
    Points : 20
    Points
    20
    Par défaut
    Salut Pedro204,

    Merci pour ta reponse. Je ne vais pas adopter ta solution. C est un peu trop bidouille a mon gout (mais au moins ca peu marché).

    Je n'ai pas envie de faire une seule unité car cela va me donner des fichiers tres tres longs (environ 70 000 lignes) si je regroupe toutes les classes ayant des dépendances circulaires.

    En Delphi, est ce qu'il est possible de mettre l'interface d'une classe dans une unité et l'implémentation des méthodes dans une autre ?

    Ludo

  8. #8
    Membre à l'essai
    Inscrit en
    Mars 2005
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 33
    Points : 20
    Points
    20
    Par défaut
    Pas con, Reisubar, le coup des methodes abstraites. Je vais essayer et je vous donne la reponse apres

    Ludo

  9. #9
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    685
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 685
    Points : 1 608
    Points
    1 608
    Par défaut
    En Delphi, est ce qu'il est possible de mettre l'interface d'une classe dans une unité et l'implémentation des méthodes dans une autre ?
    Non. Cependant on peut ruser avec des classes abstraites (enfin, qui n'ont que des méthodes abstraites), cf mon post précédent.
    "It's more fun to compute !"

  10. #10
    Membre éprouvé
    Avatar de octal
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    441
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 441
    Points : 957
    Points
    957
    Par défaut
    Bonjour,
    personnellement (ce n'est qu'un avis perso) : deux classes qui s'utilisent (font réf) l'une l'autres mutuellement provient tjr d'une mauvaise architecture objet. Il vaudrais mieux revoir les objets et leurs interdépendance (je pense que le meilleur est d'aller parcourir un petit livre de design patterns). Dans votre cas, soit il faudrais revoir tes classes, soit il faudrais utiliser des pointeurs générique qui pointerais sur tes classes, et faire des cast dans la partie implémentation vers la classe désigné. Mais cette solution je trouve qu'elle est un peu dégueu. D'autre part tu pourrait aussi t'en sortir en créant une unité commune aux deux unités (appelé dans la partie interface de chacune) dans laquelle tu définira deux interface (type IInterface ou interafce de classe) et tes classes devront alors imlémenter chacune son IInterface, et la référence q'uelle feront l'une sur l'autre se feront plutot via un Memebre du type IIterface plutot que sur le type ClassX ou ClasseY ... ca devrait te permettre de t'en sortir .. mais je ne cesserais jamais de le répéter, pour moi (et c mon avis perso) un tel pb résulte tjr d'une mauvaise architecture des classe, faudrais revoir (et cerner ou limiter) la responsabilité affectée à chacune de tes deux classe, et au lieu d'avoir systématiquement une variable membre tu type de l'autre classe, faudra peut être définir une (ou plusieurs) autres classe qui véhiculeront (et du coups découpleront) l'interaction entre tes deux classes. En fait le but del'orienté objet est de créer des modules logiciels indépendant (pour la réutilisabilité) et en interaction harmonieuse, or si tu imbrique trops tes classes les unes dans les autres, tu verra qu'elles deviendront tellement interdépendant qu'elle seront pratiquement non réutilisables et tu verra que ton soft deviendra vite un GRAND et GROS bloc monolythique qui perdra une grande partie de l'interet d'être batit sur une tech orienté objet. .. mais je le redit (pour pas me faire incendié par les anti-object ils se reconnaitront) ce n'est qu'un avis perso.
    Bon courage
    et surtout si tu trouve (chosi) une sol faites le nous savoir
    http://www.pocketmt.com GLCD Font Creator home site.

  11. #11
    Membre à l'essai
    Inscrit en
    Mars 2005
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 33
    Points : 20
    Points
    20
    Par défaut
    Merci Octal,

    Je vois assez bien les solutions que tu proposes. Je suis d accord avec toi sur le faite que reference circulaire = mauvaise architecture. Mais dans mon cas (suite a des besoins utilisateurs), j ai du mal a trouver une alternative.

    Dans mon cas, j'ai une structure d'arbre incluant des methodes de construction/destruction de l'arbre et une méthode de parcours de l'arbre. Parcours recursif classique. Pour un noeud donné (classe TNode), l'ordre de parcours des noeuds-fils dépend des données inclus dans les noeuds-fils. C'est le parcours par défaut.

    Maintenant, les utilisateurs souhaitent pour un noeud donné, imposés leur propre parcours. Donc, pour cela, a la classe TNode, je suis en train d'ajouter un objet TManager. Lors du parcours de l'arbre, si un noeud contient un TManager, le TManager est executé en priorité pour savoir dans quel ordre les noeuds-fils sont parcourus. La classe TManager contient (entre autre) un pointeur sur procedure. Cette procedure contient alors le nouveau parcours des noeuds-fils programmé par l'utilisateur comme il en envie. Le probleme est que la procedure est exécuté avec une référence sur le noeud contenant le TManager. Donc, l'objet TManager contient alors une reference sur le TNode qui l'inclus. Puisque le TNode inclus un membre TManager, j ai un probleme de reference circulaire !!!

    La solution est de faire heritée toutes mes classes de la meme classe generique. Mais, je trouve pas cela tres elegant car TNode et TManager sont des classes tres tres differentes. Donc, pas de reel raison d'hérité de la meme classe

    Ludo

  12. #12
    Membre expérimenté
    Avatar de Bloon
    Homme Profil pro
    Consultant Freelance
    Inscrit en
    Avril 2002
    Messages
    467
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant Freelance
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2002
    Messages : 467
    Points : 1 339
    Points
    1 339
    Par défaut
    Il n'y a que 2 bonnes solutions à ton problème :

    1) revoir ton modèle de classes
    2) si ces références mutuelles sont inévitables, mettre les 2 classes dans la même unité

    Comme dit octal ça peut provenir d'une mauvaise architecture, mais pas toujours. Par exemple dans la VCL, TListItems fait référence à TCustomListView qui fait lui-même référence à TListItems. Les 2 classes sont donc déclarées dans la même unité.

    Les relations parent/enfants provoquent souvent ce problème puisqu'un parent doit connaitre ses enfants et un enfant doit connaitre son parent.

    Bloon
    A lire : Les règles du club
    Delphi : La FAQ - Articles

  13. #13
    Membre à l'essai
    Inscrit en
    Mars 2005
    Messages
    33
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 33
    Points : 20
    Points
    20
    Par défaut
    Merci a tous.

    Je crois que pas le choix. J'opte pour (2) puisque la, je suis dans la situation expliquée par Bloon.

    Encore merci a tous

    Ludo

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 27/03/2006, 22h03
  2. portage delphi 5 -> delphi 2005 IFormDesigner
    Par mushy dans le forum Langage
    Réponses: 2
    Dernier message: 22/11/2005, 15h04
  3. Passage de Delphi 7 à Delphi 2005
    Par Yepazix dans le forum EDI
    Réponses: 2
    Dernier message: 24/10/2005, 11h44
  4. Réponses: 3
    Dernier message: 04/10/2005, 09h33
  5. Différence delphi 2005 / delphi 6
    Par pat.k dans le forum EDI
    Réponses: 3
    Dernier message: 21/06/2005, 17h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo