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 :

Comment dériver d'une TList sans trop de peine ?


Sujet :

Langage 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 Comment dériver d'une TList sans trop de peine ?
    Bonjour tout le monde.

    Chaque fois que je définis un composant (TMyComponent), je définis une liste associée (TMyList) qui permet de gérer des TMyComponent sans avoir à transtyper à chaque fois des items.
    Pour faire ainsi, je fais ce 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
      TMyList = class( TList )
      protected
        function GetItem( Index : Integer ) : TMyComponent;
        procedure SetItem( Index : Integer; const Value : TMyComponent );
     
      public
        property Items[ Index : Integer ] : TMyComponent read GetItem write SetItem; default;
      end;
     
    // ....
    function TMyList.GetItem( Index : Integer ) : TMyComponent;
    begin
      Result := inherited Items[ Index ] as TMyComponent
    end;
     
    procedure TMyList.SetItem( Index : Integer; const Value : TMyComponent );
    begin
      inherited Items[ Index ] := Value;
    end;
    Mon soucis est que lorsque je vais dériver le composant (TMyDerivedComponent) et que je désire faire sa liste associée, je suis obligé de redéfinir les méthodes GetItem et SetItem.
    Sans parler des autres méthodes, qu'il faut surcharger juste pour qu'elles retournent les nouveaux types afin de ne pas transtyper les composants dans le code.

    Je suis sûr qu'il existe un moyen plus simple mais je n'ai pas encore trouvé comment. Avez-vous une idée ?

    Merci.

  2. #2
    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,

    L'implementation de ta property est tout à fait logique (bonne programmation à conseiller à tous).

    Malheureseument, je crois qu'il ny a pas vraiment de methode qui puisse te faciliter la vie pour les classes dérivées.
    Ce serait contraire à la philsophie générale des types et des héritages.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  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
    Je comprends, donc lorsque je désire faire une TMyFilleList dérivée de TMyList, je dois redéfinir toutes les méthodes qui retournent un TmrComponent en faisant par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function TMyFilleList.GetByNom( aNom : string ) : TMyNewComponent;
    begin
      Result := inherited GetByNom( aNom ) as TMyNewComponent;
    end;
    C'est un moindre mal.
    Mais je me demande si niveau optimisation, si c'est judicieux car si j'encapsule plusieurs classes dérivées, cela va entrainer un certain nombre de transtypage, et si je me souviens bien, il est conseillé de ne pas trop en faire.

  4. #4
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    tu veux vraiment cassé ta tête, regarde dans le source de delphi comment, pour qu'il enregistre les composants ajouté dans un conteneur comme une forme, (si je comprend bien ce que tu veux )
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  5. #5
    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
    En fait, j'ai pas très bien compris ce que tu me conseilles de faire.
    Une TList est une liste de pointeurs, donc non typés. Il faut typer l'élément d'une TList pour pouvoir utiliser des méthodes de l'objet.
    En typant directement les items de la TMyList, je peux directement utiliser les méthodes sans faire de typage, c'est plus facile pour coder.

  6. #6
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    désoler tu peut expliqué plus
    utlisé les méthode de qoi??
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  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 154
    Points
    10 154
    Par défaut
    Récemment vu sur le forum, voir l'outil que propose waskol :
    http://www.developpez.net/forums/viewtopic.php?t=474390
    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
    Une méthode est une procédure ou fonction associée à une classe.

    Imagines, tu as déclaré un composant, TMyComponent, ayant comme méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure ShowDescription;
    Quand tu as une liste qui définie ses Items comme étant des TMyComponent, il suffit de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyList[ i ].ShowDescription;
    et non
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     ( List[ i ] as TMyComponent ).ShowDescription;
    Imagines tu as une liste TMyList de TMyComponent possédant une méthode GetByNom qui retourne un TMyComponent, si tu définies une classe fille TMyFilleList de TMyList de TMyFilleComponent, il faudra redéfinir la méthode pour qu'elle retourne des TMyFilleComponent et non des TMyComponent
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      TMyList = class( TList )
      // ...
      public
        function GetByName( aName : string ) : TMyComponent;
      end;
     
      TMyFilleList = class( TMyList )
      // ...
      public
        function GetByName( aName : string ) : TMyFilleComponent;
      end;
    Et le code de la dernière méthode de fait qu'un inherited avec le résultat transtypé en TMyFilleComponent (comme indiqué plus haut dans le topic).
    C'est un peu du code qui ne sert pas à grand chose, j'aimerais bien trouver une solution pour ne pas avoir à redéfinir l'ensemble des méthodes des classes filles, car ic je donne un exemple simple avec une seule classe fille et une seule méthode à surcharger, mais dans mon code, il doit y avoir 10 ou 20 classes avec je ne sais pas trop combien de méthodes.

  9. #9
    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 Sjrd, je viens de lire le sujet que tu as mis en lien, mais à moins que je n'ai pas suivi, ce n'est pas le même problème.
    Je ne souhaites pas à réimplémenter des classes Listes personnalisées à partir d'un TObject et avoir à refaire l'ensemble des méthodes d'une TList.
    Je souhaite pouvoir créer des classes dérivées d'une TList afin de pouvoir réutiliser les méthodes d'une TList sans avoir à les refaire, et pouvoir typer la valeur de retour de la liste et ne pas avoir à redéfinir l'ensemble des méthodes des listes personnalisées.

    Je viens de voir le programme de Waskol, mais il permet juste d'automatiser la déclaration et l'implémentation des fonctions de base de la liste personnalisée, cela ne répond pas à mon problème.

    Je ne sais pas si je suis clair dans mes propos en fait.

  10. #10
    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
    J'avais bien compris... Mais tu ne pourras pas faire mieux en Pascal & Co. Il faudrait disposer des templates de C++ pour pouvoir faire mieux. Mais d'ici que les templates soient supportées en Delphi...
    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.

  11. #11
    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
    Oui, c'est bien ce que je me disais. J'espérais qu'il existe un autre moyen.
    Tant pis, je vais rester comme je fais actuellement.

  12. #12
    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,

    J'utilise assez courament ce genre de transtypage en cascade dans des classes dérivées (et delphi l'utilise plus encore dans les bibli) , j'ai jamais rencontré de problème à ce sujet.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  13. #13
    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
    Pour l'instant moi non plus, mais j'ai entendu dire que trop transtyper pouvait ralentir l'exécution de l'application, car l'application doit rechercher dans la hiérarchie des classes laquelle implémente la fonction appellée.
    Enfin finallement, je crois que je confonds avec les méthodes virtuelles.

  14. #14
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par WebPac
    Enfin finallement, je crois que je confonds avec les méthodes virtuelles.
    Non les opérateur AS et IS s'appuie sur les RTTI à la différence du transtypage à la compilation.

  15. #15
    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 Laurent Dardenne
    Non les opérateur AS et IS s'appuie sur les RTTI à la différence du transtypage à la compilation.
    Donc cela confirme qu'il est conseillé de ne pas mettre des transtypages en cascade ?

  16. #16
    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,

    J'utilise for peu les 'as', et au lieu
    deResult := inherited GetByNom( aNom ) as TMyNewComponent;
    et j'aurais plutot écrit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Result := TMyNewComponent(inherited GetByNom( aNom )) ;
    Le résultat est équivalent, mais je ne m'étais jamais posé la question de savoir si c'était compilé différement, ce qui est effectivement très possible.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  17. #17
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par WebPac
    Donc cela confirme qu'il est conseillé de ne pas mettre des transtypages en cascade ?
    Je n'irais pas jusque là.
    D'après ton exemple les éléments de tes listes contiennent tjr le même type d'élément (est-ce tjr le cas dans ton appli ?), l'utilisation de l'opérateur AS n'est pas nécessaire dans ce cas.
    [Edit]
    Trop lent pour répondre

  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
    Graffito, je ne sais pas non plus si c'est compilé différement ni si l'une est conseillée par rapport à l'autre, c'est marrant, je n'utilise jamais ta méthode et toujours avec AS. Question de gout.

    Laurent, en général, j'aime bien créer un type de liste pour chaque type d'objet que j'ai. Ainsi, il existe des objets qui ont des descendants (du point de vue héritage) jusqu'à 3 génération, d'autres aucun, et des classes "mères", il y doit y en avoir une bonne vingtaine, avec un majorité d'entre eux, j'ai besoin de certaines méthodes du style GetByNom.
    C'était pour arriver à créer de nouvelles classes avec les classes List associées sans avoir à redéfinir les méthodes, et dans un second temps savoir ce qui est le plus optimisé.

    Mais comme l'a dit Sjrd, sans les templates, je doute qu'on puisse faire mieux.

  19. #19
    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
    Une petite précision : le transtypage ne doit pas être confondu avec l'opérateur as. L'opérateur as, c'est l'opérateur is + transtypage si True ou génération d'exception si False.
    En fait, ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ClasseEnfant := ClasseParent as TClasseEnfant;
    correspond à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if ClasseParent is TClasseEnfant then
      ClasseEnfant := TClasseEnfant(ClasseParent)
    else
      ECastError.Create(ClasseParent.ClassName + ' n''est pas un descendant de '+TClasseEnfant.ClassName);
    Autrement dit, lorsque vous savez que ClasseParent est bel et bien une instance de TClasseEnfant, utilisez le transtypage. Si vous devez vérifier que c'est bien le cas, utilisez soit l'opérateur is et un transtypage ou l'opérateur as.

    Finalement, j'ajouterai que l'opérateur as ne peut être utilisé qu'avec des classes et uniquement si ClasseParent est déclarée comme une classe dans la généalogie directe de TClasseEnfant. Par généalogie directe, j'entends les parents, grands-parents, enfants, petits-enfants etc. Mais pas les cousins ou les oncles par exemple
    En revanche, le transtypage peut être utilisé avec n'importe quels types, du moment qu'ils sont stockés sur le même nombre d'octets. Ainsi, n'importe quel TObject peut être transtypé en integer et vice versa ; par contre, un TObject ne peut être transtypé en Byte.
    Notez bien qu'il possible de "transtyper" un integer en un Byte, alors qu'ils ne sont pas stockés sur le même nombre d'octets. En fait, ce n'est pas un réel transtypage : les transtypages entre types nombres, de même que les transtypages entre types chaînes, sont compilés spécialement de façon à effectuer une véritable conversion de format.
    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.

  20. #20
    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, je suis vraiment content d'apprendre comment marche l'opérateur as.
    Du coup je sais plus si je vais garder les as ou utiliser des transtypages.

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 20/06/2014, 11h59
  2. Comment sortir d'une fonction sans nom ?
    Par kriekbellevue dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 23/11/2007, 15h00
  3. Réponses: 1
    Dernier message: 25/05/2007, 15h46
  4. Comment lancer une appli sans afficher ses fiches
    Par raoulmania dans le forum Langage
    Réponses: 5
    Dernier message: 02/09/2005, 18h07
  5. Comment mettre à jour une ligne sans doublon via déclencheur
    Par fuelcontact dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 02/08/2004, 15h56

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