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

Delphi Discussion :

Le type TMyObject n'est pas encore complètement défini


Sujet :

Delphi

  1. #1
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut Le type TMyObject n'est pas encore complètement défini
    Bonjour tout le monde,

    voici ce que je cherche à faire :
    avoir 2 classes dans 2 unités différentes et chacune des classes ayant une référence du type de l'autre classe.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    type
      TMyObject = class( TComponent )
      private
        FMyObject2 : TMyObject2;
      end;
    Et faire de même dans la déclaration de TMyObject2.
    Bien entendu, on ne peut pas mettre dans les uses interface l'unité de l'autre classe, sinon on aurait des uses circulaires.

    Je me suis dit, qu'une solution serait de mettre TMyObject2 dans le uses de MyObject puis faire une prédéclaration de TMyObject dans l'unité de TMyObject2.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    type
      TMyObject = classs;
      TMyObject2 = class( TComponent )
      private
        FMyObject : TMyObject;
      end;
    Mais dans ce cas, j'ai le message d'erreur :
    Le type TMyObject n'est pas encore complètement défini.
    J'ai l'impression que je n'ai le droit de faire une prédéclaration que dans l'unité qui déclare la classe.

    Une solution serait de mettre les 2 classes dans la même unité, mais comme chaque classe est énorme (dépasse les milliers de ligne), je préfère les garder dans des unités séparées.

    Pour l'instant, j'ai un objet qui est l'owner de l'autre, donc je passe par l'owner et je transtype, c'est pas très propre mais ça marche tant que je n'ai pas d'autre solution.

    Est-ce que faire une prédéclaration est une bonne solution et il y a une astuce que j'ai zappé ou dois-je continuer à utiliser les owner car il n'y a pas d'autre solution ?

  2. #2
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 419
    Points : 5 818
    Points
    5 818
    Par défaut
    salut

    ce que tu veut faire ne peut pas ce faire directement
    il te faut passer par un ancetre de ta classe c'est les fameux probleme de reference circulaire

    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
    Unit UMyClaseBase 
     TmyClassBase = TComponent 
     end;
    (****************************)
    unit UMyObject
    uses UMyClaseBase;
     type
      TMyObject = class( TComponent )
      private
        FMyObject2 : TmyClassBase;
      end;
    (****************************)
    unit MyObject2
    uses UMyClaseBase,UMyObject;
    type
      TMyObject2 = class(TmyClassBase)
      private
        FMyObject : TMyObject;
      end;
    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  3. #3
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Salut Phil et merci de proposer une solution, mais en utilisant une classe mère, on est obligé de faire un transtypage pour pouvoir travailler avec, ce qui ne résoud pas vraiment mon problème, c'est comme en utilisant l'owner.

  4. #4
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    ne serait-ce point une solution que d'utiliser des interfaces ?
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  5. #5
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Bonjour,

    Je ne sais pas si ça répond à la question, mais pour faire des références circulaires dans les clauses Uses de 2 units Unit1 et Unit2 , il suffit de mettre dans "uses Unit1" dans la partie implémentation de Unit2.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  6. #6
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Salut Graffito mais avec ta méthode ça ne marche pas, je le fais déjà mais on ne peut pas utiliser chacune des classes dans l'autre dans la partie declaration, on est obligé d'en avoir une utilisée qu'à partir d'implementation et ce n'est pas ce que je désire faire.

    Salut tourlourou, j'ai essayé de faire une sorte d'utilisation d'interfaces sans utiliser des interfaces et j'ai eu ces messages d'erreur :
    Le type TMyObject n'est pas encore complètement défini.
    Par contre, utiliser des interfaces, ça n'oblige pas d'instancier des méthodes utiles pour les interfaces comme le compteur de références et d'autres choses galères à utiliser ?

    As-tu un exemple simple à montrer ?

  7. #7
    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 152
    Points
    10 152
    Par défaut
    @Graffito : oui si une unité n'utilise le type de l'autre que dans sa partie implémentation Or là il s'agit bien d'avoir les références dans la partie interface des deux côtés (enfin c'est ce que j'ai cru comprendre).

    @WebPac : la solution est évidemment, comme tu l'as dit toi-même, de placer les deux classes dans la même unité. Même si elles font des milliers de lignes, c'est comme ça.

    Si l'on réfléchit un peu au sens du mot unité : il s'agit bien de construire une entité unique. À l'intérieur de cette entité, tout ou presque est possible : aussi bien faire des références circulaires entre classes qu'accéder aux variables privées d'autres classes. Mais dès qu'on sort de l'unité, celle-ci apparaît comme une enveloppe à laquelle on ne touche pas, si ce n'est en lecture à sa section interface.

    Il est donc par nature et par essence impossible de faire ce que tu veux.
    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.

  8. #8
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Merci sjrd pour ces précisions, donc ça veut dire qu'avec des interfaces ça ne marchera pas non plus, c'est dommage.

    Je vais devoir garder mes ( Owner as TMyObject ).... un peu partout dans le code, je trouve les transtypages pas très propres, mais bon tant pis, tant que ça marche.

  9. #9
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 858
    Points : 11 301
    Points
    11 301
    Billets dans le blog
    6
    Par défaut
    je ne suis pas spécialiste des interfaces (ni du reste, d'ailleurs!) ; mais je voyais les choses comme ça :

    unit 3 qui déclare 2 types d'interfaces (1 par type d'objet) avec les méthodes nécessaires

    dans chaque unité, tu fais hériter l'objet de l'interface adéquate, tu implémentes les méthodes

    comme chaque unité utilise cette unit 3, elle connaît l'interface sur l'autre objet => récupération des champs nécessaires, sans en connaître rien d'autre, ce qui est conforme au fait d'avoir des unités séparées, et des interfaces qui masquent les détails

    reste à prouver que ça marche autrement qu'en théorie...
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  10. #10
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Dès que j'ai le temps de tester, j'essaierai la méthode avec les interfaces.

    @ sjrd : si le CTRL + MAJ + C marchait parfaitement à chaque fois et ne rajoutait pas parfois les nouvelles méthodes en toute fin d'unité (et donc mélange les méthodes des différentes classes), peut-être que j'essaierai de mettre les classes dans les même unités, mais tant qu'il ne marche pas bien, je ne vais pas le faire.

  11. #11
    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 152
    Points
    10 152
    Par défaut
    Citation Envoyé par WebPac
    Je vais devoir garder mes ( Owner as TMyObject ).... un peu partout dans le code, je trouve les transtypages pas très propres, mais bon tant pis, tant que ça marche.
    Utilise plutôt TMyObject(Owner) C'est beaucoup plus court à écrire et à exécuter
    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.

  12. #12
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Citation Envoyé par sjrd
    Utilise plutôt TMyObject(Owner) C'est beaucoup plus court à écrire et à exécuter
    Voui, on gagner 2 lettre AS
    Mais pour les pointilleux, c'est moins rigoureux car ça ne teste pas le transtypage incorrect.

  13. #13
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 419
    Points : 5 818
    Points
    5 818
    Par défaut
    salut


    effectivement le transtypage est obligatoire
    mais car il y a toujour un mais tu doit le definir qu'a deux endroit
    dans le "setMonObjet" et le "getmonObjet"
    apres il te suffit de faire appele a c'est deux methode pour acceder a ton objet interne

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  14. #14
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Salut anapurna,

    mais si on ne peut pas déclarer de TMyObject dans la déclaration de TMyObject2, on ne peut pas non plus déclarer SetMonObjet et GetMonObjet qui prennet TMYObject en paramètre et en résultat de méthode.

  15. #15
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 552
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 552
    Points : 3 918
    Points
    3 918
    Par défaut
    Est-il vraiment impératif de répartir tes classes dans 2 unités séparées?

    cdlt

    e-ric

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  16. #16
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Etant donné que chaque classe dépasse les plusieurs milliers de ligne et que le CTRL + MAJ + C rajoute régulièrement les nouvelles méthodes en fin d'unité, je répondrai "oui".

  17. #17
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 419
    Points : 5 818
    Points
    5 818
    Par défaut
    salut

    je reprend mon code

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    Unit UMyClaseBase 
     TmyClassBase = TComponent 
     end;
    (****************************)
    unit UMyObject
    uses UMyClaseBase;
    implementation
     type
      TMyObject = class( TComponent )
      private
        Function getmyClass : TmyClassBase; 
        Function stMyClass(value : TmyClassBase);
        FMyObject2 : TmyClassBase;
      end;
    ...
    interface
    uses  MyObject2;
     
    Function TMyObject.getmyClass : TmyClassBase; 
    begin
      if FMyObject2 is TMyObject2  Then
        Result := FMyObject2 as TMyObject2 
      else 
        Result := nil ;
    end;
     
    Function TMyObject.setMyClass(value : TmyClassBase);
    begin
       if value is TMyObject2  Then
         FMyObject2 :=  value as TMyObject2   
       else raise Exception.Create('Erreur la classe n''est pas valide') ;
    end;
     
    end;
     
    (****************************)
    unit MyObject2
    uses UMyClaseBase,UMyObject;
    type
      TMyObject2 = class(TmyClassBase)
      private
        FMyObject : TMyObject;
      end;
    essai ceci est dit moi si cela fonctionne
    pas tester

    @+ phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  18. #18
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Salut anapurna, ta solution ne marche pas car tu mets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        Function getmyClass : TmyClassBase; 
        Function stMyClass(value : TmyClassBase);
        FMyObject2 : TmyClassBase;
    Hors il faudrait que le type soit TMyObject2 ou sinon, dans cet exemple, à chaque fois que j'utiliser GetMyClass, je dois trantyper la valeur de retour en TMyObject2.

  19. #19
    Expert confirmé
    Avatar de anapurna
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2002
    Messages
    3 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 419
    Points : 5 818
    Points
    5 818
    Par défaut
    salut

    a quoi te sert l'autoreferencement exactement ?

    @+ Phil
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  20. #20
    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 152
    Points
    10 152
    Par défaut
    Citation Envoyé par WebPac
    Mais pour les pointilleux, c'est moins rigoureux car ça ne teste pas le transtypage incorrect.
    Je suis du genre pointilleux, et je ne considère pas le transtypage comme irrigoureux. Il s'agit là de deux utilisation différentes : as quand il serait possible que l'objet ne soit pas de la bonne classe ; transtypage quand ce serait un bug du programme.
    Quid du transtypage et de l'opérateur as ?
    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.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 16
    Dernier message: 06/06/2007, 15h46
  2. Réponses: 6
    Dernier message: 23/12/2006, 17h36

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