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 :

Classe et record


Sujet :

Langage Delphi

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Points : 146
    Points
    146
    Par défaut Classe et record
    bonjour,

    Je me questionne sur les risques d'utiliser une structure pour réunir tout les champs d'une classe.

    Un exemple vaut mille mots

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    TTest = class
     
      private :
        fChamp1 : string
        fChamp2 : string
        ...
        fChampN : string
    end;
    Qui donne donc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    TChamp = record
      Champ1 : string
      Champ2 : string
      ...
      ChampN : string
    end;
     
    TTest = class
      private :
        fChamps : TChamp;
     
    end;
    Donc, quelle sont les risques les risques d'utiliser une structure comme ci-haut?

    Quelle sont les différences ? Alloc mémoire, etc.

    Note : J'utilise cette façon puisque l'héritage multiple n'existe pas en delphi et que les interfaces ne me suffise pas.

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Pour les allocations, cela ne doit pas changer grand chose en Delphi 7 (pour les plus récents, hum, ...)

    Quel est l'intéret d'avoir une structure comme ceci pour du multi-héritage, plusieurs classes se partage les mêmes données ?

    Pourquoi ne pas plutôt faire une class TCustomTest de base contenant TCustomChamp avec une propriété de type TCustomChampClass (class of TCustomChamp), et ensuite tu fais des classes qui hérite de TCustomTest comme TTestA et TTestB, l'un ayant comme TCustomChampClass que TCustomChamp et la seconde ayant TCustomChampB qui étend TCustomChamp ...

    cette cituation est finalement proche de ce que l'on trouve avec la TCollection et TCollectionItem,

    Attention, dans les Delphi récent, il me semble que record n'est plus une simple structure mais une classe très limitée ...

    Sinon voir aussi la "délégation de l'implémentation d'une interface" (c'est une rubrique de l'aide de Delphi7, ça peut te donner des idées pour créer un objet "multi-hérité" via des interfaces utilisant d'autre objet pour implémenter les différentes méthodes des interfaces ...
    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
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Points : 146
    Points
    146
    Par défaut
    Quel est l'intéret d'avoir une structure comme ceci pour du multi-héritage, plusieurs classes se partage les mêmes données ?
    Exacte, je dois partager des membres entre deux classes. Il m'est impossible d'y arriver avec l'héritage simple car la structure des deux classes ne me le permet pas. De plus, certaines sont des classes de base et commune à beaucoup d'autre classes.

    nb. Partage ne signifie pas que je dois partager les valeurs ... (par précaution )

    Corrigez moi si j'ai mal compris, mais en gros ce que je comprend c'est ç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
    15
    16
    17
    18
     
    TCustomChamp = class
      fChamp1 : string;
    end;
     
    TCustomChampClass = class of TCustomChamp
     
    TCustomChampB = class(TCustomChamp)
      fChamp2 : integer;
    end;
     
    TCustomTest= class
      fChampX : TCustomChampClass;
    end;
     
    TTestA = class(TCustomTest)
     
    end;
    Et sinon, les structures comportent elles un risque? car elles me permettent
    de faire beaucoup plus avec les champs de la classe.

    Ex: Enregistrer la structure dans un TMemoryStream, l'enregistrer dans un fichier, etc.

  4. #4
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Les Structures ne posent aucun problème, c'est juste que cela se moins extensible ...

    Ne croit pas non plus que serializé un record de string soit si simple (mieux vaut prévoir les changements de version avec des champs qui s'ajoutent) ..., tu peux aussi imaginer que tes champs soient dans une classe héritée de TPersistant et batir un gestionnaire de flux (à la façon TForm et DFM)

    Pourquoi ne pas avoir plutôt un objet intermédiaire ? qui ne contient que les données, et autour des objets qui utilise cet objet intermédiaire pour effectuer leur manipulation ... tu peux voir cela comme un objet Contexte utilisé par d'autre objets autour ... ou encore le principe d'un gros objet héritant du tétrachié d'interface utilisant la délégation d'implémentation avec une kyrielle d'objet, une sorte de Proxy finalement ...

    Sinon, je te corrige effectivement, pour pas grand chose, même si a mon avis, ce n'est pas ce que tu recherche, ... attention à ne pas partir dans une uzine à gaz ...

    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
    TCustomChamp = class
      FChamp1 : string;
    end;
     
    TCustomChampClass = class of TCustomChamp
     
    TChampB = class(TCustomChamp) // ce n'est plus custom mais spécifique !
      FChamp2 : Integer;
    end;
     
    TCustomTest = class
      FChampX : TCustomChamp;
      FChampsClass: TCustomChampClass;
    end;
     
    TTestA = class(TCustomTest)
      constructor Create();
    end;
     
    TTestB = class(TCustomTest)
      constructor Create();
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    constructor TTestA.Create();
    begin
      inherited Create();
      FChampsClass := TCustomChamp;
      FChampX := FChampsClass.Create();
    end;
     
    constructor TTestB.Create();
    begin
      inherited Create();
      FChampsClass := TChampB; // Ici !!!!
      FChampX := FChampsClass.Create();
    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

  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 : 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 445
    Points
    28 445
    Par défaut
    pour répondre à ta question, non ça ne change rien et oui c'est parfois pratique

    maintenant pour ce qui est des flux, attention aux types dynamiques dont les string et à l'alignement (voir packed)
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Points : 146
    Points
    146
    Par défaut
    Ok je vais essayer d'être plus clair pour trouver une meilleur solution.

    J'ai une classe TD1 qui hérite des fonctionnalité de TA, TB et TC.

    De plus, j'ai d'autre classe TD2, TD3 qui hérite aussi des fonctionnalité de TA, TB et TC.

    Ce que je cherche à faire c'est de pouvoir dupliquer les champs de TD1 dans une classe TE1 sans avoir à hérité des fonctionnalité de TA,TB et TC.

    Donc, TD1 DOIT hériter des fonctionnalités et TE1 ne doit pas hériter des fonctionnalités mais doivent contenir les mêmes champs ou à peu près puisque TA, TB et TC continnent quelques champs. (Seulement les champs de TD1)

    Enfin, pour partager les champs, plusieurs options s'offre à moi.

    1: faire du copier/coller des champs d'une classe à l'autre et si la modification d'un champs s'impose, ne pas oublié de modifier l'autre.

    2: Utiliser les interfaces et si la modification d'un champs s'impose, modifier l'interface. (Je n'y connais pas grand chose en interface et j'ai eu beaucoup de mauvaises expériences avec ceux-ci. De plus, l'interface m'oblige de réécrire mes champs)

    3: Utiliser une structure afin de partager les champs entre les deux classes et n'avoir à peu près rien à écrire lors de modification. En plus, la structure me permetterais d'enregistrer les champs dans un fichier, de les travailler en mémoire avec un TMemoryStream, crypter, etc.

    4: Utiliser une classe imbriquée afin de partager en protected les champs communs. Ceci revient presque à utiliser une structure.

    Ceci étant dit, y aurait il des solutions que j'aurais oubliés?

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Points : 146
    Points
    146
    Par défaut
    merci pour votre réponse Paul et du conseil

  8. #8
    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 445
    Points
    28 445
    Par défaut
    Si je comprend bien...tu veux faire 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
     
    type
      TChamps = record
        Int : Integer;
        Value :Double;
        Position : TPoint;
      end;
     
      TClasse1 = class(TAncetre1)
       private
        FChamps : TChamps;
      end;
     
      TClasse2 = class(TAncetre2)
       private
        FChamps : TChamps;
      end;
    ben oui, un record me parait très bien , tout modification dans TChamps impactera TClasse1 et TClasse2

    d'autant que tu peux déclarer des propriétés qui font référence aux éléments du RECORD

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
      TClasse2 = class(TAncetre2)
       private
        FChamps : TChamps;
       public
        property Value: Double read FChamps.Value write FChamps.Value;
      end;
    Et tu remplaceras avantageusement ce RECORD par une classe quand tu voudras lui ajouter des méthodes ou que tu voudras faire un éditeur de propriétés pour l'IDE de Delphi (au cas ou tu crées des composants installables).

    EDIT: un des avantages de cette structure est par exemple dans une méthode Clear

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    procedure TClasse1.Clear;
    begin
      FillChar(FChamps, SizeOf(FChamps), 0);
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Points : 146
    Points
    146
    Par défaut
    Merci aux deux experts (Shai et Paul)

    En gros, je m'inquiète beaucoup trop

    Dernière question, si j'utilise une classe imbriqué plutôt qu'une structure, est-ce plus compliqué de le transformé en flux?

  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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par pepi22 Voir le message
    Merci aux deux experts (Shai et Paul)

    En gros, je m'inquiète beaucoup trop

    Dernière question, si j'utilise une classe imbriqué plutôt qu'une structure, est-ce plus compliqué de le transformé en flux?
    oui et non...en fait tu vas retomber sur le même problème

    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
     
    type
      TChamps = class
      private
        FID: Integer;
        FPosition : TPoint;
        FName : string;
       public
        procedure SavetoStream(AStream: TStream);
      end;
     
    procedure TChamps.SaveToStream(AStream:TStream);
    var
      cLen: Integer;
    begin
      AStream.WriteBuffer(FID, SizeOf(FID));
      AStream.WriteBuffer(FPosition, SizeOf(FPosition));
      AStream.WriteBuffer(cLen, SizeOf(cLen));
      cLen := Length(FName);
      if cLen>0 then
        AStream.WriteBuffef(FName[1], cLen);
    end;
    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
     
    type
      TChampsRec = record
        FID : Integer;
        FPosition : TPoint;
      end;
     
      TChamps = class
      private
        FChamps: TChampsRec;
        FName: string;
       public
        procedure SavetoStream(AStream: TStream);
      end;
     
    procedure TChamps.SaveToStream(AStream:TStream);
    begin
      AStream.WriteBuffer(FChamps, SizeOf(FChamps));
      cLen := Length(FName);
      if cLen>0 then
        AStream.WriteBuffef(FName[1], cLen);
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #11
    Membre habitué
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    203
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2007
    Messages : 203
    Points : 146
    Points
    146
    Par défaut
    Merci à vous deux pour le temps que vous m'avez accordé

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

Discussions similaires

  1. Records ou Classe
    Par Max.Adorable dans le forum F#
    Réponses: 12
    Dernier message: 06/08/2008, 14h04
  2. Erreur "Type Record, Object ou Class requis"
    Par gogéta91 dans le forum Débuter
    Réponses: 5
    Dernier message: 31/07/2008, 09h16
  3. Record et classe
    Par Gweta dans le forum Débuter
    Réponses: 5
    Dernier message: 09/01/2008, 11h43
  4. Réponses: 9
    Dernier message: 10/03/2007, 08h39
  5. type record, objerct ou classe requis ?
    Par babou54 dans le forum Delphi
    Réponses: 3
    Dernier message: 10/01/2007, 13h39

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