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

Codes sources à télécharger Delphi Discussion :

Classe TArrayObject et fonction BinaryStringReplace


Sujet :

Codes sources à télécharger Delphi

  1. #1
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut Classe TArrayObject et fonction BinaryStringReplace
    Pour des besoins dans mes logiciels personnels, j'avais besoin d'une fonction qui puisse remplacer dans un fichier quelconque, dans un seul appel, plusieurs critères par d'autres, et ce indifféremment en format texte ou binaire.

    La difficulté (pour moi, en tout cas...) était de pouvoir passer à la fonction des tableaux de strings ou de "array of array of byte" et de les traiter indifféremment dans ma fonction. Voici ma solution que je propose de partager (et pour laquelle des comentaires ou améliorations sont les bienvenus).

    J'ai créé une unité ArrayObject.pas qui contient mon implémentation d'un objet capable d'encapsuler aussi bien des "array of string" que des "array of array of byte" et de les traiter en faisant abstraction de leur contenu réel. Et j'ai fait une unité RBS qui contient ma fonction utilisant ces nouveaux objets.

    Tout est dans le fichoer ZIP en pièce jointe avec le projet complet d'un programme de démo permettant de sélectionner un fichier et de le traiter, en forçant un suffixe "_converted" à la fin du nom de fichier. Un petit fichier demo1.txt est joint également.

    J'ai failli oublier: tout cela est réalisé en Delphi 6 Personal Edition.
    Fichiers attachés Fichiers attachés

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 429
    Points : 24 794
    Points
    24 794
    Par défaut
    Pourquoi CreateNew comme constructeur ?
    Ajoute un const pour tes paramètres string non modifié dans la fonction qui les reçoit avec le BrlndMM c'est un gain de temps
    faudrait travailler sur virtual et override pour utiliser le polymorphisme au lieu d'une encapsulation.

    Pour la fonction de remplacement, peut-être utiliser des Event à la place de la dépendance au TMemo/ProgressBar
    Que ce passe-t-il si un OldPattern est à cheval sur deux Buffers ?
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    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 430
    Points
    28 430
    Par défaut
    j'ai pas tout regardé mais quand je vois ça je dis ouille !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function TArrayObject.ElementCount: integer;
    begin
      result := -1;
      if ArrayType=atStringArray then result := TStringArray(fArray).ElementCount;
      if ArrayType=atByteArray then result := TByteArray(fArray).ElementCount;
    end;
    la moindre des choses serait de déclarer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    type
      TArrayObject = class
        function ElementCount: Integer; virtual; abstract;
      end;
     
      TStringArray = class(TArrayObject)
        function ElementCount: Integer; override;
      end;
     
      TByteArray = class(TArrayObject)
        function ElementCount: Integer; override;
      end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Merci à vous deux pour vos remarques. J'avoue que je n'ai pas regardé du côté de virtual, abstract, override. Faudra que j'approfondisse cela car pour le moment, cela m'échappe. Mais je vais m'y mettre !

    Concernant la remarque sur un pattern à cheval sur deux buffeurs, tel que j'ai conçu la chose, cela ne devrait pas arriver. Le lis un buffeur d'une longueur définie par une constante (32 ko dans la version actuelle), mais je limite l'analyse à une partie réduite. En fait, je détermine les longueurs minimales et maximales des critères et j'arrête la recherche dès que je suis trop près de la limite du buffeur. Puis, je reprends la lecture, non pas là où le l'avais laissée, mais là où j'avais arrêté l'analyse, à savoir à une distance équivalente à la longueur minimale des critères. Ainsi, cette partie non analysée se retrouvera au début du buffeur lors de la prochaine lecture et le critère pourra être trouvé.

    En rédigeant ces lignes, je me rends compte qu'il aurait fallu s'arrêter à une distance correspondant à la longueur du plus long critère et non du plus court. Le fichoer ZIP ci-joint contient cette correction. Pas encore les modifictations selon vos conseils techniques - faut que je comprenne d'abord.

    Merci pour vos remarques - je remets l'ouvrage sur le métier...
    Fichiers attachés Fichiers attachés

  5. #5
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    j'ai pas tout regardé mais quand je vois ça je dis ouille !
    Ben... j'ai dû mal m'exprimer dans mon post initial.

    Je voulais créer une classe (TArrayObject dans mon cas) qui est capable de contenir et gérer deux classes différentes (TStringArray et TByteArrar dans moncas). Ma classe TArrayObject, via des propriétés et méthodes générales, devait pouvoir gérer les classes dépendantes de façon transparente, sans que je sache, vu de m'extérieur, quelle classe est contenue à l'intérieur de TArrrayObject.

    Pour cette raison, je crée ma classe TArrayObject en lui indiquant le type de classe interne à créer ainsi que sa dimension, comme dans:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      OldPat := TArrayObject.CreateNew(atStringArray,2);
    Ensuite, j'agis uniquement syr TArrayObject, comme par exemple pour charger sonn contenu:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      OldPat.LoadArrayElementFromString(0,'Bonjour');
      OldPat.LoadArrayElementFromString(1,'chien');
    Ensuite, je n'utilise que TArrayObject (OldPat dans ce cas) pour trairer les patterns qui s'y trouvent. Vu de l'application, j'ignore tout du contenu et de la structure interne de TArrayObject. Avec la suggestion de VIRTUAL et OVERRIDE, j'ai l'impression qu'on inverse le raisonnment: on crée une classe "parent" dont on "dérive" deux classes "enfant", chacune ayant les mêmes méthodes. Je fais ça souvent dans d'autres contextes, mais ceci ne me permet pas de passer un identifiant unique à ma fonction de de le traiter dans ma fonction sans qu'elle sache ce que la classe passée en paramètre contient reellement.

    Ceci dit, en réfléchissant à tout cela, j'ai découvert un résidu de code provenant de mes premiers essais, qui est obsolète et qui brouille donc la compréhension, dans le programme principal. Je l'ai supprimé, et la version apurée est dans le ZIP ci-joint. Ainsi, le programme principal ne connaît que TArrayObject, de même que la fonction dans l'unité RBS. Les "helper class" nommées TStringArray et TByteArray ne sont jamais utilisées explicitement. Tout l'intérêt de la chose se situe là.
    Fichiers attachés Fichiers attachés

  6. #6
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 483
    Points : 2 734
    Points
    2 734
    Billets dans le blog
    10
    Par défaut
    Il faut approfondir certaines notions comme le TStrings et TStringlist avant d'aller plus loin pour ne pas recréer ce qui existe déjà. Si besoin est je peux te passer des extraits du livre que j'ai écrit sur Delphi

  7. #7
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    @ ALWEBER

    Merci de ta proposition. Je suis toujours preneur quand le peux apprendre quelque chose.
    Je connais bien TStringList que j'utilise souvent.
    Je suis beaucoup mois à l'aise avec TStrings que je n'utilise jamais directement.

    Ceci dit, si mon besoin était de passer uniquement des listes de chaînes de caractères en paramètre, j'aurais bien sûr utilise une TStringList
    avec le critère de recherche comme texte de chaque élément et le critère de remplacement en tant qu'objet comme objet associé.
    Malheureusement, cela ne marche pas avec des critères binaires pouvant contenir des octets "difficiles" comme des zéros binaires.
    Là, seul un "array of array of byte" est possible, encapsulé dans mon implémentation dans un TByteArray.
    Ceci était la raisin initiale de la création de mon objet TArrayObject, gérant de façon transparente des tableaux de strings et
    des tableaux de byte en 2 dimension, ce qui correspond à des "strings binaires".

    J'ai supprimé des résidus de traçage dans la fonction, issus de ma phase de debug.
    En fichier ZIP joint, voici la versioin "nettoyée".
    Fichiers attachés Fichiers attachés

  8. #8
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 671
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 671
    Points : 13 065
    Points
    13 065
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    ...de le traiter dans ma fonction sans qu'elle sache ce que la classe passée en paramètre contient reellement.
    C'est la définition même du polymorphisme

    Le problème est que tu instancies directement TArrayObject ce qui t'oblige à conserver une référence sur le type réel et de procéder à des tests systématiques sur chaque fonction.
    Utiliser une méthode de classe plutôt qu'instancier directement TArrayObject te permettrait de retourner ce type réel et de te passer de tous ces tests.

    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
    type
      TArrayObject = class abstract
      public
        class function CreateArray(aType :TArrayType; aCount :integer) :TArrayObject;
      end;
     
    TStringArray = class(TArrayObject);
     
    TByteArray = class(TArrayObject);
     
    class function TArrayObject.CreateArray(aType: TArrayType; aCount: integer): TArrayObject;
    begin
      case aType of
        atStringArray : Result := TStringArray.Create(aCount);
        atByteArray   : Result := TByteArray.Create(aCount);
        else raise Exception.Create('Type non supporté');
      end;
    end;

  9. #9
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Je vais essayer, Andnotor !

  10. #10
    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 430
    Points
    28 430
    Par défaut
    bon alors on reprend, car c'est le principe même de la programmation orientée objet

    quand j'utilise un TStream par exemple, j'ignore si c'est un TFileStream, un TMemoryStream, un TResourcceStream, ou quoi que ce soit d'autre...car ils sont tous descendants de TStream et j'utilise les méthodes de TStream sans me préoccuper de savoir si c'est un fichier, une zone mémoire ou une ressource.

    quand tu écris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function TArrayObject.ElementCount: integer;
    begin
      result := -1;
      if ArrayType=atStringArray then result := TStringArray(fArray).ElementCount;
      if ArrayType=atByteArray then result := TByteArray(fArray).ElementCount;
    end;
    tu codes le principe même d'un objet mais sans faire de l'objet

    TArrayObject.ElementCount ne sais pas ce qu'il doit retourner de lui-même, donc méthode virtuelle (et abstraite ou pas selon qu'on veuille faire une implémentation par défaut qui retourne -1 ou pas)

    TStringArray et TByteArray connaissent leur nombre d'éléments, donc ils surchargent la méthode pour donner leur réponse.

    et à l'usage tu pourras écrire
    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
     
    procedure remplaceFichier(const fichier: string; a: TArrayObject);
    begin 
       // ici je ne sais pas si je manipule  des byte ou des string et je m'en fiche
    end;
     
    var
      a: TByteArray;
      b: TStringArray;
    begin
      a := TByteArray.Create;
      // remplir a
      remplaceFichier('test.txt', a); // là j'ai besoin de byte 
     
      b := TStringArray.Create;
      // remplir b
      remplaceFichier('test.txt', b); // et là de string
    end;
    mais pour pouvoir écrire cela il faut que TByteArray et TStringArray dérivent de TArrayObject
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #11
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Merci, Paul Toth !

    Là, je comprends mieux. Je vais tenter d'appliquer tout cela et reviendrai avec le résultat.

  12. #12
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Voilà ma nouvelle version après implémentation de méthodes virtuelles abstraites dans la classe TArrayObject, selon les conseils de Paul TOTH.

    En effet, c'est beaucoup plus simple et beaucoup plus propre. A l'exécution, le résultat est identique.

    Un grand MERCI - j'ai appris une chose importante qui me sera utile !
    Fichiers attachés Fichiers attachés

  13. #13
    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 430
    Points
    28 430
    Par défaut
    ok, c'est plus propre, mais encore deux petites remarques

    le constructor est supposé s'appeler Create et non CreateNew, ce n'est pas une contrainte c'est une bonne pratique, TForm possède un constructor CreateNew mais il a un usage particulier car il ne charge pas le DFM

    les destructors ne servent à rien dans le cas présent, les tableaux dynamiques sont des types managés, ils sont automatiquement détruits par Delphi
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  14. #14
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    D'accord. J'ai supprimé le destructor et remplacé CreateNew âr Create.
    J'ai donc dû créer une nouvelle méthode SetArrayLength pour remplacer mon paramètre de CreateNew.
    Tout fonctionne à nouveau. Ci-joint la nouvelle version.
    Fichiers attachés Fichiers attachés

  15. #15
    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 430
    Points
    28 430
    Par défaut
    Citation Envoyé par KlausGunther Voir le message
    D'accord. J'ai supprimé le destructor et remplacé CreateNew âr Create.
    J'ai donc dû créer une nouvelle méthode SetArrayLength pour remplacer mon paramètre de CreateNew.
    Tout fonctionne à nouveau. Ci-joint la nouvelle version.
    il est tout à fait possible de mettre des paramètres à un constructor quelque soit son nom

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    constructor TMaClass.Create(CeQUeJeVeux...);
    begin
      inherited Create(AutreChoseAuBesoin...); // s'il faut appeler le constructor hérité qui n'a pas la même signature
      ...
    end;
    tu pourrais même faire un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    constructor TStringArray.Create(const Strings: array of string);
    var
      I: Integer;
    begin
      inherited Create;
      SetLength(fStringArray, Length(Strings));
      for I := 0 to Length(Strings) - 1 do 
       fStringArray[I] := Strings[I];
    end;
     
    begin
      TStringArray.Create(['Hello', 'le chien']);
    end;
    et encore c'est car je reste compatible D5/6/7, sinon je serais passer par un TArray<string> qu'on peut affecter directement à fStringArray

    en D5/6/7 un "const x:array of string" est un tableau ouvert et non un tableau dynamique, ce n'est pas la même chose. Dans les dernières versions, on peut déclarer un tableau dynamique directement.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  16. #16
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    D'accord. Merci pour cela - je vais noter ça pour un usage ultérieur.
    Dans le contexte de l'objet TArrayObject, je préfère finalement garder Create sans paramètres
    et utiliser la méthode SetArrayLength ce qui me permettra, le cas échéant, de changer dynamiquement la dimension.

    Merci pour ce cours magistral qui m'a fait bien progresser.

  17. #17
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 483
    Points : 2 734
    Points
    2 734
    Billets dans le blog
    10
    Par défaut EXtraits manuels
    Ci joint un peu de doc comme promis
    Images attachées Images attachées

  18. #18
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Merci beaucoup, AlWeber ! J'ai jeté un rapide coup d'oeil et je vois qu'il me reste plein de choses à apprendre, en particulier les interfaces, mais pas que.
    J'aurai de quoi occuper mes soirées.

    A toutes fins utiles, je joins la toute dernière version de mon code, contenant les adaptations suggérées par Paul Toth, deux nouvelles méthodes permettant de charger les attays à partir de TStrinList, TMemo ou TListbox et une interface visuelle permettant de saisir les critères de recherche/remplacement pour la fonction de remplacement. Ces objets sont passés en paramètre (pour utilisation directement par Delphi) ou par handle (sauf TStringList bien sûr) pour utilisation de ce code dans une DLL appelée par un programme non-Delphi (Panoramic dans mon cas). Je sais, ça ne change rien sur le fond, mais c'est juste un plus pour la facilité d'utilisation.
    Fichiers attachés Fichiers attachés

  19. #19
    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 430
    Points
    28 430
    Par défaut
    tu n'as vraiment pas les réflexes de la programmation objet

    TStringList, TMemo.Lines et TListBox.Items sont tous les trois dérivés de TStrings qui reprend ce principe d'ancêtre commun, tu devrais donc simplement déclarer LoadArrayFromStrings(Strings: TStrings)

    par ailleurs, ton ancêtre commun TArrayObject n'a pas besoin d'être purement virtuel, il peut très bien implémenter cette fonction en utilisant SetArrayLength() et LoadArrayElementFromString()

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    procedure TArrayObject.LoadArrayFromStrings(Strings: TStrings);
    var
      Index: Integer;
    begin
      SetArrayLength(Strings.Count);
      for Index := 0 t o Strings.Count - 1 do
        LoadArrayElementFromString(Index, Strings[Index]);
    end;
    et c'est là toute la beauté de l'objet, une seule fonction pour charger les strings sans même savoir à quoi tu as affaires et ça marche dans tous les cas car tu sais que tous les dérivés de TArrayObject surchargent SetArrayLength() et LoadArrayElementFromString()

    au bout de 25 ans de programmation objet, ces mécanismes deviennent des automatismes

    le premier principe que j'applique c'est que si deux fonctions se ressemblent à 90% c'est qu'il y a très probablement moyen de la transformer en une seule fonction avec éventuellement un paramètre en plus ou - comme dans le cas présent - la recherche d'un ancêtre commun

    et avec les dernières versions tu peux ajouter des fonctions utiles (même si je ne suis pas forcément fan)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    type
      TArrayObject = class
        ...
        procedure TArrayObject.LoadArrayFromMemo(Memo: TMemo);  inline;
      end;
     
    procedure TArrayObject.LoadArrayFromMemo(Memo: TMemo);
    begin
      LoadArrayFromStrings(Memo.Lines);
    end;
    le fait de mettre "inline" implique que la fonction ne sera pas une fonction mais directement le code ajouté là où tu l'utilise et qu'il n'y aura donc aucune différence entre les deux lignes suivantes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      ArrayObject.LoadArrayFromMemo(Memo1); // avec inline c'est la même chose que la ligne ci-dessous
      ArrayObject.LoadArrayFromStrings(Memo1.Lines);
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  20. #20
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Mars 2010
    Messages : 287
    Points : 164
    Points
    164
    Billets dans le blog
    1
    Par défaut
    Je n'avais pas vu ça... Je vais adapter mon code avec "LoadArrayFromStrings" selon ta suggestion.

    Voici la version modifiée. J'ai remplacé les deux méthodes LoadArrayFromMemoObject et LoadArrayFromMemoHandle en méthodes propres à TArrayObject, sans virtualisation.
    Merci ! C'est beaucoup plus simple comme ça !

    A titre d'exemple, je charge OldPattern par LoadArrayFromStringsByHandle et NewPattern par LoadArrayFromStrings.

    EDIT 29/01/2020 à 18;30

    Correction d'un bug dans TBinaryAray.
    Fichiers attachés Fichiers attachés

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

Discussions similaires

  1. classe friend vs fonctions globales vs ...
    Par khayyam90 dans le forum C++
    Réponses: 8
    Dernier message: 24/03/2006, 00h19
  2. Glut / Class / Pointeur sur fonction
    Par areS. dans le forum GLUT
    Réponses: 5
    Dernier message: 02/12/2005, 21h50
  3. Comparaison entre les classes et les fonctions
    Par Ashgenesis dans le forum Langages de programmation
    Réponses: 6
    Dernier message: 08/09/2005, 20h09
  4. [class] Ajouter class devant une fonction
    Par Pedro dans le forum Langage
    Réponses: 12
    Dernier message: 07/03/2005, 14h11
  5. Réponses: 4
    Dernier message: 17/03/2004, 18h24

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