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

  1. #1
    Nouveau membre du Club
    Déclarer un objet dans un objet (pb de déclaration enfin je crois)
    Bonjour

    Je déclare mes objets comme suit :
    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
    type
      TGu = class
      strict private
        FPeriode: integer;
        FValeur: integer;
      public
        property Periode: integer read FPeriode write FPeriode;
        property Valeur: integer read FValeur write FValeur;
        constructor Create(); overload;
      end;
     
      TBarre = class
      strict private
        Fdate: string;
        FOpen: double;
        Flow: double;
        Fhigh: double;
        Fclose: double;
        FIndic: TGu;
      public
        property date: string read Fdate write Fdate;
        property open: double read FOpen write FOpen;
        property low: double read Flow write Flow;
        property high: double read Fhigh write Fhigh;
        property close: double read Fclose write Fclose;
        property Indic: TGu read FIndic write FIndic;
        constructor Create(); overload;
      end;
     
    implementation
     
    constructor TGu.Create;
    begin
      FPeriode := 0;
      FValeur := 0;
    end;
     
    constructor TBarre.Create;
    begin
      Fdate := '';
      FOpen := 0;
      Flow := 0;
      Fhigh := 0;
      Fclose := 0;
      FIndic.Periode := 0;
      FIndic.Valeur := 0;
    end;


    Dans mon code j ai une collection d objet "Barre" que je tente de remplir comme cela :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Barre := TBarre.Create();
            Barre.Date := b_Dte;
            Barre.Open := b_Open;
            Barre.high := b_High;
            Barre.low := b_Low;
            Barre.Close := b_Close;
            Barres.Add(Barre);


    Ceci souleve une exception et pointe du doigt FIndic.Periode := 0; dans ma declaration.

    Je m initie à la POO et tout fonctionnait avant que je tente de declarer / utiliser FIndic: TGu;

    Merci de votre aide

  2. #2
    Membre chevronné
    AJouter
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    indic := TGU.create

    dans le create de TBarre

  3. #3
    Nouveau membre du Club
    Merci, cela fonctionne.

    Toutefois j ai activé le ReportMemoryLeaksOnShutdown et cela fait état d une fuite mémoire au niveau du TGu.

    Désolé si je n emplois pas la bonne terminologie.

    Merci

  4. #4
    Rédacteur/Modérateur

    Bonjour,

    Puisqu'il y a eu indic := TGU.create il ne faut pas oublier de le supprimer.
    Il faut rajouter un destructeur à la classe TGu et y écrire un FreeAndNil(Findic);
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  5. #5
    Nouveau membre du Club
    Merci pour ton aide.

    Je cherche à comprendre parce que je ne peux pas utiliser Findic dans le destructeur de TGu puisqu il a été créé dans le TBarre non ?
    il est non reconnu dans le destructeur de TGu mais est reconnu dans le destructeur de TBarre mais cela n a aucune incidence.

    Désolé, c est la première fois que j utilise cela

  6. #6
    Rédacteur/Modérateur

    mea culpa j'ai lu trop rapidement, évidemment le destructeur de TBarre
    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
     
    TGu = class
      strict private
        FPeriode: integer;
        FValeur: integer;
      public
        property Periode: integer read FPeriode write FPeriode;
        property Valeur: integer read FValeur write FValeur;
        constructor Create(); overload;
      end;
     
    TBarre = class
      strict private
        Fdate: string;
        FOpen: double;
        Flow: double;
        Fhigh: double;
        Fclose: double;
        FIndic: TGu;
      public
        property date: string read Fdate write Fdate;
        property open: double read FOpen write FOpen;
        property low: double read Flow write Flow;
        property high: double read Fhigh write Fhigh;
        property close: double read Fclose write Fclose;
        property Indic: TGu read FIndic write FIndic;
        constructor Create(); overload;
        destructor destroy; override;
      end;
     
    ...
     
    { TBarre }
     
    constructor TBarre.Create;
    begin
    FIndic:=TGu.Create;
    //
    end;
     
    destructor TBarre.destroy;
    begin
      FreeAndNil(FIndic);
      inherited;
    end;
     
    { TGu }
     
    constructor TGu.Create;
    begin
    //
    end;
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  7. #7
    Nouveau membre du Club
    J ai enlevé le résolu parce que je me trouve confronté à une autre difficulté que je crois être due à ma déclaration.

    Dans une première boucle je remplis ma collection d objects Barres avec des TBarre à l exception de 'Indic' que je remplis dans une seconde boucle.

    Je fais, et ç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
    for I := T_Max - 1 to T_Max - 1 do
      begin
        Gus := TObjectList<TGu>.Create();
        for T := T_Min to T_Max do
        begin
          Gu := TGu.Create;
          Gu.Periode := T;
          Gu.Valeur := ExtractB(T, I, 1.96, Barres);
          Gus.Add(Gu);
        end;
        Barres[I].Indic.Add(Gus); <---MON ERREUR EST LA
        Gus.destroy;
      end;


    Je pense donc que je devrais declarer Indic en tant que TObjectList<TGu> mais j ai essayé et je suis totalement perdu car je ne sais pas comment déclarer les propriétés Read et Write.

    Merci pour votre patience ...

  8. #8
    Rédacteur/Modérateur

    Bonjour,

    On ne change rien à TGu si ce n'est, peut-être le create pour plus de facilités
    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
    TGu = class
      strict private
        FPeriode: integer;
        FValeur: integer;
      public
        property Periode: integer read FPeriode write FPeriode;
        property Valeur: integer read FValeur write FValeur;
        constructor Create(Periode, Valeur : Integer); overload; 
      end;
    ..
    constructor TGu.Create(Periode, Valeur : Integer);
    begin
    FPeriode:=Periode;
    FValeur:=Valeur;
    end;


    Puisqu'il s'agit d'une liste j'ai préféré renommer indic (unique) en indicateurs (pluriel)
    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
     
    TBarre = class
      strict private
        Fdate: string;
        FOpen: double;
        Flow: double;
        Fhigh: double;
        Fclose: double;
        FIndicateurs: TObjectList<TGu>;
      public
        property date: string read Fdate write Fdate;
        property open: double read FOpen write FOpen;
        property low: double read Flow write Flow;
        property high: double read Fhigh write Fhigh;
        property close: double read Fclose write Fclose;
        property Indicateurs: TGu read FIndicateurs write FIndicateurs;
        constructor Create(); overload;
        destructor destroy; override;
      end;
     
    { TBarre }
     
    constructor TBarre.Create;
    begin
    FIndicateurs:=TObjectList<TGu>.Create;
    //
    end;
     
    destructor TBarre.destroy;
    begin
      FreeAndNil(FIndicateurs); // à vérifier 
      inherited;
    end;


    utilisation, bien que je ne comprenne pas la logique des boucles !
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for I := T_Max - 1 to T_Max - 1 do // bizarre
      begin
        for T := T_Min to T_Max do
          Indicateurs.Add(TGU.Create(T,ExtractB(T, I, 1.96, Barres));  // plus simple avec la surcharge du create de TGU 
      end;
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  9. #9
    Nouveau membre du Club
    Merci, c est parfait !

    La logique des boucles vient du fait que je lis un gros fichier de cotations boursières que je parse pour en extraire les données qui me servent à créer les barres.

    Une fois importé je calcule Indics dans une autre boucle que je peux appeler n importe où avec n importe quelles valeurs ce qui me permet de ne pas avoir à relire le fichier.

    Je débute et c est ce qui me semblait plus logique mais je suis ouvert à toute proposition.

  10. #10
    Rédacteur/Modérateur

    Je vais en rester à la partie "déclarations" des classes.
    Ce qui me paraissait bizarre c'est for I := T_Max - 1 to T_Max - 1 do que j'avais d'ailleurs commenté d'un // bizarre
    comme en fait il n'y a passage qu'une seule fois (i=T_max-1) c'est là où la logique m'échappe mais bon, il y a un barres qui traîne qui semble être un tableau (qui aurait certainement pu être lui aussi un TObjectList<TBarre> peut-être ? Et là un for uneBarre in Barres do cela aurait été pas mal )
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  11. #11
    Expert éminent sénior
    gros fichier de cotations boursières
    Attention à ce que la structure objet ne soit pas lourde et lente pour une importante volumétrie
    Deux DataSet lié en Master\Detail peuvent être plus pertinents pour de lourdes données
    Après, nous n'avons pas forcément la même notion de gros, un fichier de 10 Millions de Gu à 100o l'instancesize de l'objet, nous sommes à 1 Go en mémoire l'air de rien

    Par dessus les TDataSet vous pouvez construire des objets métiers rendant l'utilisation plus élégante, un l'objet n'est qu'un adapateur entre un code OO et un code DB


    Cela n'a pas été soulevé mais dans constructor Create(); overload; le overload n'est pas nécessaire car TGu = class est synonyme de TGu = class(TObject) et il n'y que Create comme constructeur, simplement comme ceci suffit constructor Create(); comme lorsque l'on redéfinie une méthode statique

    Après, le overload peut-être nécessaire pour introduire un constructeur alternatif avec paramètres sans masquer le constructeur Create
    le override interviendra la d'une redéfinition d'un constructeur virtuel;
    le reintroduce permet dans des cas extrêmes de masquer une méthode virtuelle

    autre point, je protégerais un membre de type classe comme FIndicateurs dont la durée de vie est géré par l'instance de TBarre
    property Indicateurs: TGu read FIndicateurs; Pas de write
    D'ailleurs cela ne serait pas plutôt property Indicateurs: TObjectList<TGu> read FIndicateurs; ?

    Ajoutons le type TGus = TObjectList<TGu> pour écrire FIndicateurs: TGus;

    Ou alors être plus courageux property Indicateurs: TGus read FIndicateurs write SetIndicateurs;

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure SetIndicateurs(Value: TGus);
     
    ...
     
    procedure TBarre.SetIndicateurs(Value: TGus);
    begin 
      FIndicateurs.Clear(); // OwnsObjects par défaut, cela libère tous les TGu
      FIndicateurs.AddRange(Value); // Attention à la libération de Value qui ne doit pas libérer les objets recopiés dans FIndicateurs
    end;
    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

  12. #12
    Nouveau membre du Club
    Les valeurs identiques dans cette boucle étaient pour ne tester que sur une seule itération .
    Cette boucle est imbriquée dans une autre qui parcours toutes les barres.

    Je teste tout ça ce soir de retour du boulot.

    merci encore

  13. #13
    Expert éminent sénior
    j'ai lu en diagonal, mais que je vois ça

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    for I := T_Max - 1 to T_Max - 1 do
      begin
        Gus := TObjectList<TGu>.Create();
        for T := T_Min to T_Max do
        begin
          Gu := TGu.Create;
          Gu.Periode := T;
          Gu.Valeur := ExtractB(T, I, 1.96, Barres);
          Gus.Add(Gu);
        end;
        Barres[I].Indic.Add(Gus); <---MON ERREUR EST LA
        Gus.destroy;
      end;


    j'ai l'impression qu'on pourrait écrire

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     type
      TGus = record
        Periode: Integer;
        Valeur: Integer;
      end;
     
      TBarre = class
      ...
        Indic: array[T_Min..T_Max] of TGus;
      ...
      end;


    ou quelque chose approchant non ?
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store