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 :

Redéfinition de la méhode IndexOf d'un TObjectList


Sujet :

Langage Delphi

  1. #1
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut Redéfinition de la méhode IndexOf d'un TObjectList
    Bonjour à tous,

    Actuellement, je suis sur un petit projet et je suis confronté à un petit souci.
    J'ai une classe produit que voici (elle est simplifiée pour expliquer mon souci).

    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
    unit UProduit;
     
    interface
     
    type TProduit = class
      private
        FRefProduit           : integer;
        FNomProduit           : string;
        FStockProduit         : integer;
        FPrixUnitaireProduit  : double;
      public
        constructor Create(aRefProduit    : integer;
                           aNomProduit    : string;
                           aStockProduit  : integer;
                           aPrixUnitaireProduit : double);
    end;
     
    implementation
     
    { TProduit }
     
    constructor TProduit.Create(aRefProduit: integer; aNomProduit: string;
      aStockProduit: integer; aPrixUnitaireProduit: double);
    begin
      FRefProduit := aRefProduit;
      FNomProduit := aNomProduit;
      FStockProduit := aStockProduit;
      FPrixUnitaireProduit := aPrixUnitaireProduit;
    end;
     
    end.
    J'ai une "collection" de produits dont voici la classe :

    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
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    unit CollectionDeProduits;
     
    interface
     
    uses Contnrs, UProduit;
     
    type
      TCollectionDeProduits = class(TObjectList)
     
      private
        function GetItem(Index: integer): TProduit;
        procedure SetItem(Index: integer; const Value: TProduit);
      public
        function Add(leProduit: TProduit): integer;
        function Remove(leProduit: TProduit): integer;
        function IndexOf(leProduit: TProduit): integer;
        procedure Delete(Index: integer);
        property Items[Index: integer]: TProduit Read GetItem Write SetItem; default;
      end;
     
    {----------------------------------------------------------------}
    {                                                                }
    {                       }IMPLEMENTATION{                         }
    {                                                                }
    {----------------------------------------------------------------}
     
    function TCollectionDeProduits.Remove(leProduit: TProduit): integer;
    begin
      Result := inherited Remove(leProduit);
    end;
     
    function TCollectionDeProduits.IndexOf(leProduit: TProduit): integer;
    begin
      Result := inherited IndexOf(leProduit);
    end;
     
    function TCollectionDeProduits.Add(leProduit: TProduit): integer;
    begin
      Result := inherited Add(leProduit);
    end;
     
    function TCollectionDeProduits.GetItem(Index: integer): TProduit;
    begin
      Result := TProduit(inherited GetItem(index));
    end;
     
    procedure TCollectionDeProduits.SetItem(Index: integer; const Value: TProduit);
    begin
      inherited setItem(index, Value);
    end;
     
    procedure TCollectionDeProduits.Delete(index: integer);
    begin
      inherited Delete(index);
    end;
     
    end.
    Et voici là où ça bloque. Je fais un indexOf pour savoir si un produit P existe dans la collection, mais ça ne fonctionne pas.

    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
    44
    45
    46
    47
    48
    unit UPrincipale;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, Buttons, ExtCtrls, CollectionDeProduits;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
        tabProduit : TCollectionDeProduits;
     
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    uses UProduit;
    {$R *.dfm}
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      produit : TProduit;
      index : integer;
    begin
      produit := TProduit.Create(1, 'test', 1, 12);
      index := tabProduit.IndexOf(produit); 
      if(index = -1)then
        tabProduit.Add(produit)
      else
        ShowMessage(IntToStr(index));
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      tabProduit := TCollectionDeProduits.Create;
    end;
     
    end.
    Le souci, c'est qu'IndexOf me renvoie toujours -1. J'ai essayé de chercher comment redéfinir la méthode pour dire la comparaison soit faite sur les attributs de ma classe produit, mais je ne parviens pas à implémenter la méthode. D'après ce que j'ai pu lire, il faut définir l'interface de comparaison ICompare, ainsi qu'Equals ... Est-ce exact ?
    Pouvez-vous m'indiquer comment résoudre mon souci avec un exemple ?

    Merci

  2. #2
    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 : 54
    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
    IndexOf est utilisé pour savoir si une l'Instance d'un objet est dans la liste, pas pour savoir s'il existe un objet ayant les mêmes attributs.

    pas de ICompare dans Delphi 6

    j'imagine que tu voudrais quelque chose de cet ordre :
    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
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      produit : TProduit;
      index : integer;
    begin
      produit := TProduit.Create(1, 'test', 1, 12);
      index := tabProduit.Equal(produit); 
      if(index = -1)then
        tabProduit.Add(produit)
      else
      begin
        produit.Free; /// !!!!
        ShowMessage(IntToStr(index));
      end;
    end;
    dans ce cas j'ajouterais une méthode "Equal(AProduit: TProduit): Boolean;" à la classe TProduit pour comparer deux produits, méthode exploitée par la liste pour chercher un produit égal.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Salut Paul,

    Merci pour ton explication.
    IndexOf est pour moi plus intéressant vu qu'il renvoie la position de l'objet dans la liste. Avant, je parcourais le TObjectList jusqu'à trouver le bon élément, et je renvoyais l'index... mais je voulais ce coup-ci comprendre comment faire avec IndexOf ... (PS : Je suis sous D2009).

    En tout cas, merci pour le petit Free que j'ai oublié !

  4. #4
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Salut
    Citation Envoyé par ero-sennin Voir le message
    ... mais je voulais ce coup-ci comprendre comment faire avec IndexOf
    Paul a répondu à ta question ou interrogation.

    Citation Envoyé par Paul TOTH Voir le message
    IndexOf est utilisé pour savoir si une Instance d'un objet est dans la liste, pas pour savoir s'il existe un objet ayant les mêmes attributs.
    IndexOf va te renvoyer une valeur sup. à -1, uniquement si tu pointes sur la même instance du Produit.
    P1 et P2 (2 instances de TProduit) peuvent posséder les mêmes attributs, IndexOf(P2) ne te reverra pas l"instance de P1 (ou plutôt son index dans la liste).

    Puisque tu es sous D2009, je verrais bien une classe générique TList<TProduit> avec un comparateur de ton cru.

    @+ Claudius.

  5. #5
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Salut Cl@udius ,

    Oui en effet, je cherche à utiliser une chose qui n'est pas faite pour ce que j'ai envie de faire ...
    Sinon, pour l'histoire des génériques, ba justement, j'étais parti dessus au début ... J'avais même codé le comparateur comme l'explique Sjrd dans son tutoriel.

    Je trouvais ça "lourd" pour juste la comparaison. Surtout que ma collection d'objets n'a pas pour but de changer de type

    En gros, j'avais fait ceci :
    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
    interface
     
    TProduitComparer = class(TComparer<TProduit>)
       function Compare(const Left, Right: TProduit): Integer; override;
     end;
     
    ...
     
     private
      tabProduitTicket : TList<ProduitTicket>;
     
     
    implementation
     
    function TProduitComparer.Compare(const Left, Right: ProduitTicket): Integer;
    begin
     if Left.idProduit = Right.idProduit then
      result := 0;
     if Left.idProduit > Right.idProduit then
      result := 1;
     if Left.idProduit < Right.idProduit then
      result := -1;
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      tabProduit := TList<TProduit>.Create(TProduitComparer.Create);
    end;
    Le petit hic, c'est que ça ne m'en dit pas plus sur la position de l'objet dans la liste ... Donc j'suis coincé aussi non ?

  6. #6
    Expert éminent sénior
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Points : 10 008
    Points
    10 008
    Par défaut
    Citation Envoyé par ero-sennin Voir le message
    Je trouvais ça "lourd" pour juste la comparaison.
    Pourquoi lourd ? Une simple méthode de comparaison !

    Citation Envoyé par ero-sennin Voir le message
    Surtout que ma collection d'objets n'a pas pour but de changer de type
    N'ai pas saisi ce que tu veux dire par là.

    Citation Envoyé par ero-sennin Voir le message
    Le petit hic, c'est que ça ne m'en dit pas plus sur la position de l'objet dans la liste ... Donc j'suis coincé aussi non ?
    Erreur, IndexOf fait appel au comparateur !

    @+

  7. #7
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    A vu de nez, je dirais que ce dont tu as besoin, c'est plutôt d'un dictionnaire.

    Tu gères une liste de produits. Les produits sont identifiés par une référence.
    Tu veux faire l'indexof pour savoir s'il existe déjà un produit qui possède cette référence. Et j'imagine que si c'est le cas, tu voudrais pouvoir retrouver l'instance du produit existant.

    C'est exactement le but du dictionnaire. Puisque tu es en D2009 il ne faut pas t'en priver :

    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
     
    var
      ProduitDictionary : TDictionary<integer, TProduit>;
      Produit : TProduit;
    begin
       ....
     
      if not ProduitDictionary.ContainsKey(1)
      then begin
        Produit := TProduit.Create(1, 'test', 1, 12)
        ProduitDictionary.Add(Produit.RefProduit, Produit);
      end
      else begin
        Produit := ProduitDictionary[1]; 
      end;
    ou encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      if not ProduitDictionary.TryGetKey(1, Produit)
      then begin
        Produit := TProduit.Create(1, 'test', 1, 12)
        ProduitDictionary.Add(Produit.RefProduit, Produit);
      end;

  8. #8
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Citation Envoyé par Cl@udius Voir le message
    Pourquoi lourd ? Une simple méthode de comparaison !
    Certes... C'est que j'ai pas l'habitude surement

    Citation Envoyé par Cl@udius Voir le message
    N'ai pas saisi ce que tu veux dire par là.
    Si je ne me trompe pas, le but des génériques c'est bien de pouvoir définir une classe de type T... Moi, dans mon cas, le type sera uniquement un TProduit, et rien d'autre. J'ai pas conçu la classe pour qu'elle "s'adapte" à un autre type.

    Citation Envoyé par Cl@udius Voir le message
    Erreur, IndexOf fait appel au comparateur !
    Ba mince alors Faut que je reteste voir... Dois y avoir un truc que j'ai mal fait...

    Citation Envoyé par Franck SORIANO Voir le message
    A vu de nez, je dirais que ce dont tu as besoin, c'est plutôt d'un dictionnaire.

    Tu gères une liste de produits. Les produits sont identifiés par une référence.
    Tu veux faire l'indexof pour savoir s'il existe déjà un produit qui possède cette référence. Et j'imagine que si c'est le cas, tu voudrais pouvoir retrouver l'instance du produit existant.

    C'est exactement le but du dictionnaire. Puisque tu es en D2009 il ne faut pas t'en priver :

    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
     
    var
      ProduitDictionary : TDictionary<integer, TProduit>;
      Produit : TProduit;
    begin
       ....
     
      if not ProduitDictionary.ContainsKey(1)
      then begin
        Produit := TProduit.Create(1, 'test', 1, 12)
        ProduitDictionary.Add(Produit.RefProduit, Produit);
      end
      else begin
        Produit := ProduitDictionary[1]; 
      end;
    ou encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
      if not ProduitDictionary.TryGetKey(1, Produit)
      then begin
        Produit := TProduit.Create(1, 'test', 1, 12)
        ProduitDictionary.Add(Produit.RefProduit, Produit);
      end;
    Salut Franck!

    Je te dirai que c'est exactement ça. Un produit est identifié par sa référence. Si on ajoute un produit ayant une même référence, on met à jour sa quantité uniquement... Donc en effet, c'est une approche intéressante que tu viens de fournir.
    Je regarderai ça tranquillement mais au vu de ce que tu viens de présenter, je pense que c'est là dessus que je partirai Merci

  9. #9
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Sinon, pour répondre qu'en même à ta question à la base, tu dois pouvoir t'en sortir en surchargeant les méthodes Equals et GetHashCode de la classe TProduit.

    L'indexOf du TList<T> va faire appel à une implémentation par défaut de ICompare<T> qui dans le cas d'un TObject doit appeler sa méthode Equals.
    L'implémentation par défaut de Equals, teste l'égalité des instances, comme celà a été expliquée.
    Mais si tu surcharges Equals tu peux tester l'égalité des références produits au lieu de l'égalité des instances.

    L'indexof devrait alors fonctionner tel que tu le souhaites.

    Lorsqu'on surchage Equals, il faut également surcharger GetHashCode car deux objets identiques (Equals = true) doivent également avoir la même clé de hashage.

    Je n'ai pas fait le test en Delphi, mais c'est comme ça que ça marche en Java ou .Net. Donc je pense qu'ils ont dû copier le fonctionnement (et un coup d'oeil rapide dans les sources semble dire la même chose ).

  10. #10
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Merci pour ton éclaircissement sur le fonctionnement des méthodes Equals et GetHashCode.

    J'essaie de mettre en pratique les différentes solutions que vous m'avez proposé même si je pense rester sur le Dictionnaire, qui, à mon sens, répond parfaitement à la problématique.

    Sinon, c'est vrai que je n'ai pas pensé à regarder dans les sources ...

    Je mets en résolu car même si je n'ai pas encore codé la solution, vos réponses m'ont permis d'avoir tous les éléments en main pour dire d'y arriver.

    Merci à tous

  11. #11
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Citation Envoyé par ero-sennin Voir le message
    J'essaie de mettre en pratique les différentes solutions que vous m'avez proposé même si je pense rester sur le Dictionnaire, qui, à mon sens, répond parfaitement à la problématique.
    Oui et surtout, ce sera beaucoup plus performant que les autres solutions.
    La recherche dans un dictionnaire est indépendante de la taille du dictionnaire ( O(1) ), contrairement à la recherche dans une liste qui sera en O(ln(n)) si la liste est triée et O(n) sur une liste avec un scan séquentiel.

  12. #12
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Je reviens vers vous car j'essaie d'appliquer la surcharge d'Equals (car je suis curieux de voir si ça va fonctionner) à la classe TProduit mais je ne parviens pas à mes fins ...

    Voici ce que j'ai ajouté :

    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
    unit UProduit;
     
    interface
     
    type TProduit = class(TObject)
      private
        FRefProduit           : integer;
        FNomProduit           : string;
        FStockProduit         : integer;
        FPrixUnitaireProduit  : double;
      public
        constructor Create(aRefProduit    : integer;
                           aNomProduit    : string;
                           aStockProduit  : integer;
                           aPrixUnitaireProduit : double);
        //...
        function Equals(obj: TObject): Boolean; override;
        function GetHashCode: Integer;override;
    end;
     
    implementation
     
    { TProduit }
    //...
    function TProduit.Equals(obj: TObject): Boolean;
    begin
      Result := (obj.ClassType = self.ClassType) and
    ((obj as TProduit).getRefProduit = self.FRefProduit);
    end;
     
    function TProduit.GetHashCode: Integer;
    begin
    Result := Integer(Self);
    end;
     
    end.
    Je n'ai modifié que la classe TProduit, les autres classe reste identique...
    J'ai loupé quelques choses (une fois de plus ? ).

    Merci

  13. #13
    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
    Le Equals m'a l'air correct, mais le HashCode est foireux. Ce devrait être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function TProduit.GetHashCode: Integer;
    begin
      Result := FRefProduit;
    end;
    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.

  14. #14
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Salut Sjrd,

    Après application de ta modif, ça n'a rien changé... L'appel à indexOf ne déclenche pas la méthode Equals de ma classe TProduit. (J'ai mis un point d'arrêt pour m'en persuader ). Est ce que ça viendrait du fait que je fasse appel à indexOf de la classe TCollectionDeProduits ?

  15. #15
    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
    Peux-tu donner le code en entier, tel que tu l'as pour l'instant ?
    Avec les éléments que j'ai, je ne vois pas le problème.
    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.

  16. #16
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Voici le code dans un projet test.
    Fichiers attachés Fichiers attachés

  17. #17
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    En effet, le getHashCode était foireux...

    Equals est utilisé par les "nouvelles" listes génériques. Il faut que tu utilises un TObjectList<TProduit> comme ancêtre de TCollectionDeProduits et non pas une ancienne TObjectList.

    Remarque : Avec la liste générique, les éléments de TCollectionDeProduits seront déjà naturellement typés en TProduit. Tu n'auras plus besoin de déclarer de propriété Items pour les typer, ni bien sûr les accesseurs qui vont avec.
    En fait, tu n'auras peut-être même pas besoin de TCollectionDeProduits...

  18. #18
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Une fois de plus, merci pour tes explications Franck.
    Donc pour les personnes ayant une version de delphi antérieur à 2009, ils ne pourront pas surcharger la méthode Equals afin de l'appliquer dans le cas de l'utilisation d'indexOf ...

    En effet, le fait de typer le TObjectList me rendra la tâche plus simple

    Sinon, la méthode du TDictionary fonctionne très bien (testé hier soir).
    Comme dit plus haut, je risque de garder cette méthode mais par curiosité, j'ai envie de les tester toutes...

  19. #19
    Rédacteur/Modérateur
    Avatar de ero-sennin
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2005
    Messages
    2 965
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Nord (Nord Pas de Calais)

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 2 965
    Points : 4 935
    Points
    4 935
    Par défaut
    Rebonsoir,

    Je vous embête une dernière (?) fois de plus car je n'arrive pas à comprendre pourquoi le compilateur me sort une Erreur dans l'onglet Structure (je ne sais pas si vous voyez ce que je veux dire).

    J'ai 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
    procedure TForm1.Button2Click(Sender: TObject);
    var
      produit : TProduit;
      index : integer;
     begin
      if not ProduitDictionary.ContainsKey(1)then
      begin
        Produit := TProduit.Create(1, 'test', 1, 12);
        ProduitDictionary.Add(produit.getRefProduit, Produit);
      end
      else
      begin
        ShowMessage(IntToStr(ProduitDictionary[1].getRefProduit));
      end;
    end;
    Avec la classe TProduit qui reste inchangée.
    Sur la ligne suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ShowMessage(IntToStr(ProduitDictionary[1].getRefProduit));
    Le compilateur me met :
    TDictionary `2' ne contient pas un membre nommé 'getRefProduit' à la ligne ...
    Ca compile et fonctionne par contre..

    Par contre, ceci fonctionne (plus de message "d'erreur"):
    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
    procedure TForm1.Button2Click(Sender: TObject);
    var
      produit : TProduit;
      index : integer;
     begin
      if not ProduitDictionary.ContainsKey(1)then
      begin
        Produit := TProduit.Create(1, 'test', 1, 12);
        ProduitDictionary.Add(produit.getRefProduit, Produit);
      end
      else
      begin
        produit := ProduitDictionary[1];
        ShowMessage(IntToStr(produit.getRefProduit));
      end;
    end;
    Pourtant, le TDictionary doit forcément me renvoyer un élément de type TProduit, donc la première méthode est forcément bonne non ?
    C'est le compilateur qui fait des siennes ?

    Merci pour votre éclaircissement

  20. #20
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 173
    Points
    4 173
    Par défaut
    Citation Envoyé par ero-sennin Voir le message
    je n'arrive pas à comprendre pourquoi le compilateur me sort une Erreur dans l'onglet Structure (je ne sais pas si vous voyez ce que je veux dire).
    Si je te dis que je n'ai jamais vu l'audit d'erreur fonctionner correctement , ça répond a ta question ?

    D'une façon général, il semble être perdu sur les génériques. Si tu lui indique une variable du type de l'élément du générique, il s'y retrouve et se rend compte que la méthode existe.
    En revanche, lorsqu'il travail sur un élément du générique, il semble incapable de faire le lien avec le type de l'élément de la liste.

    Heureusement, le compilateur lui travaille correctement.

    C'est le compilateur qui fait des siennes ?
    Disons qu'il n'y a pas UN compilateur mais plusieurs. Le "compilateur" qui fait l'audit de code, l'autocompletion... s'appelle le compilateur Kibitz. Ce dernier doit être capable de travailler du source incomplet, avec des erreurs de syntaxe... et surtout, il s'exécute dans l'IDE pendant la saisie du code. Il faut qu'il consomme peu de ressources.
    En un mot, il ne peut pas faire une compilation complète de l'ensemble du source et se base sur différentes heuristiques pour s'y retrouver.
    Ce qui veut dire que son travail n'est pas parfait et qu'il peut faire des erreurs.

    Ensuite, tu as le véritable compilateur qui fait une compilation complète du code.

    Sur les génériques, tu as un problème assez simple : Le générique est en réalité un patron qui dit au compilateur de créer un nouveau type, en remplaçant le type joker, par le type réel. Si tu déclares deux listes génériques avec des types différents, le compilateur génèrera deux types listes bien dissociés.
    En revanche, le compilateur Kibitz ne travaille que sur la syntaxe. Il n'est pas capable d'identifier le type réel dans la liste.

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

Discussions similaires

  1. [ArrayList] indexOf()
    Par phoebe dans le forum Collection et Stream
    Réponses: 5
    Dernier message: 08/11/2004, 17h52
  2. [C#] Prob IndexOf sous Pocket Pc avec des guillemets
    Par freddyboy dans le forum Windows Mobile
    Réponses: 7
    Dernier message: 10/06/2004, 09h57
  3. [Héritage] Redéfinition méthode
    Par petit-ourson dans le forum Langage
    Réponses: 9
    Dernier message: 06/05/2004, 16h06
  4. [MFC] redéfinition de BEGIN_MESSAGE_MAP
    Par SethPech dans le forum C++Builder
    Réponses: 2
    Dernier message: 10/03/2004, 13h59
  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