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 :

TObjectList et TObjectList<T> : compatibles ?


Sujet :

Langage Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 149
    Points : 61
    Points
    61
    Par défaut TObjectList et TObjectList<T> : compatibles ?
    Bonjour,

    je viens de voir dans le code d'un de mes collaborateurs la chose suivante :

    une variable de type TObjectList<TMachin> est passé en argument à une fonction qui attends un TObjectList. Comme la version générique de "TOjectList" n'hérite pas de la version classique (les classes génériques ont une implémentation "parallèle" à leur homologue non générique) il a simplement hardcasté en "TObjectList".

    Et là je me dis "horreur !" ça ne marchera pas et provoquera des erreurs de violations d'accès et autres... et bien non, tout fonctionne bien, comme si le compilateur, lors d'un hardcast, essayait de faire une conversion "propre" d'un type en un autre. Personnellement je ne comprends pas, j'ai du louper quelque chose mais pour moi un hardcast ne fait que forcer le type pour permettre la compilation mais aucune opération de conversion. D'ailleurs la seule différence avec le "soft" cast est que dans ce cas le compilo vérifie d'abord que le type est compatible (hérite ou pour une interface implémente)...

    Alors visiblement je me plante, quelqu'un pourrait-il m'expliquer comment cela fonctionne ?

    Au debug j'ai pu voir que la fonction utilise les méthodes "Count" et "Get" de TOjbectList (en réalité de TList duquel il hérite), et qu'elles sont appelées tout à fait normalement dans la classe TList. Pour info la méthode "Get" n'existe même pas dans la version générique "TList<T>", elle a été renommée "GetItem"... alors y-a-t-il de la magie dans le compilo Dephi ou bien autre chose que j'ai zappé ???

  2. #2
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 730
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 730
    Points : 5 391
    Points
    5 391
    Par défaut
    Si je ne dis pas de bêtise, la liste générique hérite de la liste basique. La différence entre une liste basique et une liste générique réside dans le fait que la liste générique gère elle-même les opérations courante sur la liste en se chargeant de caster dans le type passer entre les balises "<" et ">".

    En forçant le cast d'un liste générique en une liste basique, la mécanique automatique apportée par la liste générique est rompue et l'objet utilise les méthode de son ancêtre

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 149
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par popo Voir le message
    Si je ne dis pas de bêtise, la liste générique hérite de la liste basique. La différence entre une liste basique et une liste générique réside dans le fait que la liste générique gère elle-même les opérations courante sur la liste en se chargeant de caster dans le type passer entre les balises "<" et ">".

    En forçant le cast d'un liste générique en une liste basique, la mécanique automatique apportée par la liste générique est rompue et l'objet utilise les méthode de son ancêtre
    Justement il n'y a pas d'héritage entre les deux classes (générique et non générique), c'est pourquoi je n'arrive pas à comprendre pourquoi cela fonctionne...

  4. #4
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    Peut etre que le compilateur te fait un cadeau
    Il me semble que c'est le cas quand tu fais des cast entre string / WideString / PChar / PWideChar, il remplace le cast brutal par un appel de fonction du genre "_LStrFromPChar" (dans system.pas). Il fait peut etre pareil pour les generiques de base de la VCL ...

  5. #5
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    Citation Envoyé par ZZZzzz2 Voir le message
    Justement il n'y a pas d'héritage entre les deux classes (générique et non générique), c'est pourquoi je n'arrive pas à comprendre pourquoi cela fonctionne...
    je pense que ton collègue à beaucoup de chance

    prenons TObjectList qui dérive de TList:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      TList = class(TObject)
      private
        FList: TPointerList; //  = array of Pointer;
        FCount: Integer;
        FCapacity: Integer;
    TObjectList<> dérive de TList<>

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      TList<T> = class(TEnumerable<T>)
      private
        FItems: array of T;
        FCount: Integer;
        FComparer: IComparer<T>;
    FCount se trouve au même endroit dans les deux objets, et la fonction Get utilise FList qui se trouve au même endroit que FItems

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function TList.Get(Index: Integer): Pointer;
    begin
      if Cardinal(Index) >= Cardinal(FCount) then
        Error(@SListIndexError, Index);
      Result := FList[Index];
    end;
    il peut donc utiliser Count et Items[] sans que ça plante ^^

    par contre, il suffit qu'il fasse appel à une méthode de TList qui modifie FCapacity et là il aura une belle erreur en modifiant FComparer

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 149
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    je pense que ton collègue à beaucoup de chance

    prenons TObjectList qui dérive de TList:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      TList = class(TObject)
      private
        FList: TPointerList; //  = array of Pointer;
        FCount: Integer;
        FCapacity: Integer;
    TObjectList<> dérive de TList<>

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      TList<T> = class(TEnumerable<T>)
      private
        FItems: array of T;
        FCount: Integer;
        FComparer: IComparer<T>;
    FCount se trouve au même endroit dans les deux objets, et la fonction Get utilise FList qui se trouve au même endroit que FItems

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function TList.Get(Index: Integer): Pointer;
    begin
      if Cardinal(Index) >= Cardinal(FCount) then
        Error(@SListIndexError, Index);
      Result := FList[Index];
    end;
    il peut donc utiliser Count et Items[] sans que ça plante ^^

    par contre, il suffit qu'il fasse appel à une méthode de TList qui modifie FCapacity et là il aura une belle erreur en modifiant FComparer

    Ah oui, et je viens de comprendre pourquoi l'appel à " TList<T>.GetItem" se transforme automagiquement par un appel à "TList.Get"... ces deux fonctions ne sont pas déclarées "au même endroit" dans la classe mais il s'agit de méthodes non virtuelles, et donc indépendantes de l'instance. De ce fait, et comme on accède aux éléments par la propriété "Items" qui appelle "TList.Get" en interne la méthode est retrouvée statiquement par rapport à la classe "TObjectList". Ceci explique cela, effectivement il s'agit pour le coup d'un bon coup de bol et le code va être modifié car on ne peut pas laisser une telle chose. Je suis rassuré (je n'aime pas ne pas comprendre )

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

Discussions similaires

  1. [TObjectList]Sauvegarde/Chargement
    Par ghost942 dans le forum Langage
    Réponses: 4
    Dernier message: 22/02/2006, 07h59
  2. TObjectList et variables...
    Par eponette dans le forum Langage
    Réponses: 15
    Dernier message: 15/09/2005, 15h40
  3. TobjectList contenant des TstringList
    Par SchpatziBreizh dans le forum Langage
    Réponses: 10
    Dernier message: 08/07/2005, 16h17
  4. Supprimer un élément d'une TObjectList
    Par Lung dans le forum Langage
    Réponses: 15
    Dernier message: 30/05/2005, 17h32
  5. Propriété tableau et TObjectList
    Par Mouss26 dans le forum Langage
    Réponses: 3
    Dernier message: 07/03/2003, 14h32

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