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 :

Attributs d'un record en property non modifiables


Sujet :

Langage Delphi

  1. #1
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut Attributs d'un record en property non modifiables
    Bonjour tout le monde.

    Je mets un record en champ privé d'un objet, puis je mets une property avec read et write sur ce record. Ensuite dans le code, le compilo me dit qu'on ne peux pas modifier le record. La solution que j'ai trouvé est d'utiliser une variable intermédiaire, faire les modifs dessus, puis de faire une égalité entre ma property et cette variable.
    Je trouve ça lourd et pas élégant, existe-t-il une solution plus simple ?

    Merci pour votre aide.

  2. #2
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 897
    Points : 1 561
    Points
    1 561
    Par défaut
    Une possibilité serait de créer non pas un Record mais une classe descendante de TObjet. Puis de surcharger la méthode create et destroy de ta classe principale pour créer et détruire cet objet.

    Exemple de 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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    type
     
      TRTest= class(TObject)  //classe héritée de TObject et non un record
        x,y: string;
      end;
     
      TForm1 = class(TForm)
        ...
      private
        { Déclarations privées }
     
        FTRTest: TRTest;
     
        procedure setTest(Value: TRTest);
     
      public
        { Déclarations publiques }
     
        constructor Create(AOwner: TComponent); override; 
     
        destructor Destroy; override;
     
        property Test: TRTest read FTRTest write setTest;
      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
    ...
    implementation
     
    {$R *.DFM}
     
    constructor TForm1.Create(AOwner: TComponent);
    begin
      inherited;
      FTRtest := TRTest.Create;  //création de l'objet
    end;
     
    destructor TForm1.Destroy;
    begin
      FTRTest.Free;  //libération
      inherited;
    end;

    On ne passe plus par une variable intermédiaire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TForm1.setTest(Value: TRTest);
    begin
     FTRtest := value;
    end;
    En espérant répondre à ta question.

    Cordialement
    Pensez à utiliser les tags dans le titre.
    Avant de poser une question reportez-vous à la FAQ Delphi
    Respectez les règles du forum.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    45
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2004
    Messages : 45
    Points : 34
    Points
    34
    Par défaut
    De quel type est ta propriété ?

    Code ?

  4. #4
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Salut Pascal, ben non, tu ne réponds pas vraiment à la question, car faire un objet au lieu d'un record est bien plus lourd à gérer. Je voudrais pouvoir faire un record pour rassembler des champs dans mes objets, les rassembler par fonction pour ne pas avoir pelle melle tout mélangé dans mes objets.

    Avec ce que tu donnes, il faudrait donc créer et détruire ces sous objets à la création et destruction de mes objets conteneurs. Hors, je crée déjà pas mal d'objet, et je voudrais pas trop alourdir mon code juste pour ne pas avoir à passer par une variable intermédiaire.

    En fait, voici un exemple qui montre ce que je veux dire :
    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
    type
     
      TMyRecord = record
        A: Integer;
        B: Integer;
      end;
     
      TMyObjet = class(TComponent)
      private
        FMyRecord: TMyRecord;
     
      public
        MyRecord: TMyRecord read FMyRecord write FMyRecord;
      end;
     
     
    // Plus loin dans le code, dans une fonction sur une fiche par exemple :
    function TForm1.Toto;
    begin
      MyObjectGlobal.MyRecord.A := 10; // N'est pas accepté par le compilo.
    end;
    Avec ce code, le compilateur dit :
    La partie de gauche n'est pas affectable
    J'ai vérifié et la property est avec un read et un write.

    Comment le faire sans alourdir le code ?

    Merci pour votre aide.

  5. #5
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 897
    Points : 1 561
    Points
    1 561
    Par défaut
    Citation Envoyé par WebPac
    , car faire un objet au lieu d'un record est bien plus lourd à gérer.
    Plus lourd ??, personnellement je ne trouve pas. En tout cas c'est bien plus pratique.
    Pensez à utiliser les tags dans le titre.
    Avant de poser une question reportez-vous à la FAQ Delphi
    Respectez les règles du forum.

  6. #6
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Pascal, mes records ne servent qu'à ordonner et regrouper des champs dans mes objets, je ne pense pas faire des objets pour le faire, déclarer le constructeur, destructeur, propriétés, méthode et tout ça, j'ai déjà mes objets qui ont tout ce qu'il faut et je souhaite organiser les attributs.
    Pour moi un objet n'est pas fait pour être simplement un conteneur d'information.

    Enfin, ceci est un autre débat que nous ne devrions pas faire partir en Troll, je voudrais savoir s'il existe une solution simple à mon problème.
    Et aussi est-ce que quelqu'un sait pourquoi Delphi considère qu'on ne peut pas modifier les valeurs des records dans ce cas là car je ne comprends pas du tout pourquoi il me fait ça.

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 298
    Points : 318
    Points
    318
    Par défaut
    Pourquoi ne pas créer une propriété par élement du record ? sinon si ta propriété est un pointeur sur le record, cela devrait marcher.

  8. #8
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par WebPac
    Avec ce que tu donnes, il faudrait donc créer et détruire ces sous objets à la création et destruction de mes objets conteneurs.
    Avec les record aussi...

    Citation Envoyé par cpdump
    Pourquoi ne pas créer une propriété par élement du record ?
    Effectivement cela donne :
    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
      pMyRecord=^TMyRecord;
      TMyRecord = record
        A: Integer;
        B: Integer;
      end;
     
      TMyObjet = class
      private
        FMyRecord : TMyRecord;
        Ptr       : pMyRecord ;
      public
        property MyRecordA: Integer read FMyRecord.A write FMyRecord.A;
        property MyRecordB: Integer read FMyRecord.B write FMyRecord.B;
        property MyPRecord: pMyRecord read Ptr write Ptr;
        Constructor Create;
      end;
     
    var MyObjectGlobal:TMyObjet;
     
    Constructor TMyobjet.Create;
    begin
     inherited;
     MyPRecord:=@FMyRecord;
    end;
     
    begin
     MyObjectGlobal:=TMyObjet.Create;
     
     MyObjectGlobal.MyRecordA := 10;
     MyObjectGlobal.MyRecordb := 11;
     Writeln(MyObjectGlobal.MyRecordA);
     Writeln(MyObjectGlobal.MyRecordb);
     Readln;
     
     Writeln(MyObjectGlobal.MyPRecord^.A);
     Writeln(MyObjectGlobal.MyPRecord^.b);
     Readln;
     
     MyObjectGlobal.MyPRecord^.A := 22;
     MyObjectGlobal.MyPRecord^.b := 33;
     
     Writeln(MyObjectGlobal.MyRecordA);
     Writeln(MyObjectGlobal.MyRecordb);
     Readln;
    end.
    Citation Envoyé par cpdump
    sinon si ta propriété est un pointeur sur le record, cela devrait marcher.
    Oui mais dans ce cas existe-t-il encore un intérêt d'utiliser une propriété ?

    Je préfére aussi le démarche de Pascal qui nécessite plus de code mais offre une meilleure protection.
    Et en cas de possible migration vers .NET pas de probléme ( ça c'est pour le troll )

  9. #9
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Citation Envoyé par Laurent Dardenne
    Citation Envoyé par WebPac
    Avec ce que tu donnes, il faudrait donc créer et détruire ces sous objets à la création et destruction de mes objets conteneurs.
    Avec les record aussi...
    On n'a pas besoin de créer dynamiquement un record, juste lui affecter des valeurs par défaut.


    Citation Envoyé par cpdump
    Pourquoi ne pas créer une propriété par élement du record ?
    Tout simplement, car je voudrais utiliser un record pour rassembler les attributs et donc leurs propriétés pour ne pas alourdir l'objet. L'intérêt du record était justement de ne pas lister un grand nombre de propriétés non classées.

    Citation Envoyé par Laurent Dardenne
    Citation Envoyé par cpdump
    sinon si ta propriété est un pointeur sur le record, cela devrait marcher.
    Oui mais dans ce cas existe-t-il encore un intérêt d'utiliser une propriété ?
    En fait, il existe beaucoup d'utilités pour travailler directement avec des pointeurs en Delphi ? Et n'est-il pas mieux de s'en passer ?

    Citation Envoyé par Laurent Dardenne
    Je préfére aussi le démarche de Pascal qui nécessite plus de code mais offre une meilleure protection.
    Et en cas de possible migration vers .NET pas de probléme ( ça c'est pour le troll )
    En fait, je vois toujours pas l'utilité d'utiliser un objet comme simple conteneur alors que Delphi a définit le record justement pour ça.

    Citation Envoyé par webpac
    Et aussi est-ce que quelqu'un sait pourquoi Delphi considère qu'on ne peut pas modifier les valeurs des records dans ce cas là car je ne comprends pas du tout pourquoi il me fait ça.
    Pas de réponse ? C'est quand même bizarre ce point.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 298
    Points : 318
    Points
    318
    Par défaut
    Citation Envoyé par WebPac
    En fait, il existe beaucoup d'utilités pour travailler directement avec des pointeurs en Delphi ? Et n'est-il pas mieux de s'en passer ?
    Quand les records sont alloués dynamiquement, on est bien obligé d'utiliser les pointeurs.

    Citation Envoyé par WebPac
    En fait, je vois toujours pas l'utilité d'utiliser un objet comme simple conteneur alors que Delphi a définit le record justement pour ça.
    Un objet permet un accès controlé à ses menbres contrairement à un record.

  11. #11
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Citation Envoyé par cpdump
    Citation Envoyé par WebPac
    En fait, il existe beaucoup d'utilités pour travailler directement avec des pointeurs en Delphi ? Et n'est-il pas mieux de s'en passer ?
    Quand les records sont alloués dynamiquement, on est bien obligé d'utiliser les pointeurs.
    Je ne compte toujours pas allouer dynamiquement les record, je ne vais pas le faire dynamiquement pour résoudre mon problème alors que la situation dirait qu'il est préférable de le faire statiquement.

    Citation Envoyé par cpdump
    Citation Envoyé par WebPac
    En fait, je vois toujours pas l'utilité d'utiliser un objet comme simple conteneur alors que Delphi a définit le record justement pour ça.
    Un objet permet un accès controlé à ses menbres contrairement à un record.
    Oui, c'est vrai, on peut mettre des accesseurs et des mutateurs, mais si je n'utilisais pas un record, je mettrais de toute facon directement le champ placé en privé.
    Si j'avais vraiment besoin de contrôler les accés, je le ferrais en property avec accesseurs et mutateurs.

    C'est pas que je veux pas le faire en objet, mais j'ai toujours pas vu dans mon cas l'utilité d'utiliser un objet qui ne serra qu'utilisé en interne dans un objet en tant que champ, sans méthode ni rien.

  12. #12
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Mars 2004
    Messages
    897
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 897
    Points : 1 561
    Points
    1 561
    Par défaut
    A priori delphi ne traite l'enregistrement qu'en lecture seule et c'est pour cela que tu ne peux pas lui affecter de valeur. Résultat obtenu en lisant l'aide sur ce message d'erreur.

    Si l'on passe par un pointeur alors là il est tout à fait possible d'affecter des valeurs, mais cette solution ne te convient pas car il faut à chaque fois allouer la variable dynamique donc coder le constructeur et destructeur de tes classes.
    D'autre part et comme le dit Laurent, il faut maintenant oublier les pointeurs car il n'est plus recommandé de les utiliser si l'on veut un jour porter son code sur .Net.

    Par conséquent tu ne peux hélas pas utiliser directement un record car le compilateur le traitera toujours comme un objet en lecture seule.

    Ce qui me pousse à te signaler que l'idée de la classe dérivant d'un TObjet est peut être la solution la moins mauvaise quoi qu'un peu lourde à ton goût.

    Cordialement
    Pensez à utiliser les tags dans le titre.
    Avant de poser une question reportez-vous à la FAQ Delphi
    Respectez les règles du forum.

  13. #13
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Citation Envoyé par Pascal Jankowski
    Si l'on passe par un pointeur alors là il est tout à fait possible d'affecter des valeurs, mais cette solution ne te convient pas car il faut à chaque fois allouer la variable dynamique donc coder le constructeur et destructeur de tes classes.
    D'autre part et comme le dit Laurent, il faut maintenant oublier les pointeurs car il n'est plus recommandé de les utiliser si l'on veut un jour porter son code sur .Net.
    De toute façon, je n'ai pas vraiment eu besoin d'utiliser des pointeurs encore en Delphi et je ne comptais pas m'y mettre pour ce seul problème. Delphi gère suffisament bien les objets par référence pour ne pas avoir à utiliser directement les pointeurs.

    Coder le constructeur et le destructeur, je le fais pour tous mes objets, ce n'est pas un problème de rajouter quelques lignes de code pour eux, ce que je disais, c'est que pour résoudre le problème en utilisant un objet dérivé de TObject au lieu d'un record, cette solution imposait de créer les constructeurs et destructeurs de cet objet et je ne parlais pas des objets qui contiennent les records.

    Citation Envoyé par Pascal Jankowski
    Par conséquent tu ne peux hélas pas utiliser directement un record car le compilateur le traitera toujours comme un objet en lecture seule.
    C'est justement ce point que je comprends pas, parce qu'un record dans une fonction ou en paramètre n'est pas en lecture seule lui, mais celui qui est en champ d'un objet possède ses attributs en lecture seule. Et lui même ne l'est pas, puisqu'on peut faire une égalité de record.

    Citation Envoyé par Pascal Jankowski
    Ce qui me pousse à te signaler que l'idée de la classe dérivant d'un TObjet est peut être la solution la moins mauvaise quoi qu'un peu lourde à ton goût.

    Cordialement
    Merci pour cette solution, je vais rester avec ma première solution qui est de passer par une variable temporaire, qui serra modifiée attribut par attribut, puis mon record = cette variable temporaire.
    C'est pas génial non plus comme solution.

    A priori, il n'en existe pas qui soit comme je l'aurrais voulu, tant pis c'est pas grave, je vais mettre [Résolu].

  14. #14
    Membre chevronné
    Avatar de Pierre Castelain
    Inscrit en
    Avril 2002
    Messages
    523
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 523
    Points : 1 943
    Points
    1 943
    Par défaut
    Si tu tiens absolument à continuer à utiliser des records, tu peux ruser comme 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
     
      TRec = record
        A, B: Integer;
      end;
      PRec = ^TRec;
     
      TTest = class
      private
        FRec: TRec;
        function GetLeRecord: PRec;
      public
        property LeRecord: PRec read GetLeRecord;
      end;
     
    { TTest }
     
    function TTest.GetLeRecord: PRec;
    begin
      result:= @FRec;
    end;

  15. #15
    Membre confirmé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Points : 512
    Points
    512
    Par défaut
    Merci Pierre Castelain, je vais voir ça plus tard, j'ai dû passer à la suite en utilisant une pirouette (cacahouette) et maintenant j'ai plus trop le temps d'y retourner, je pense ne pas être le seul dans ce cas là.

    Juste une question, puisque tu passes par pointeur, il faudra donc allouer et désallouer la mémoire dynamiquement ?

  16. #16
    Membre chevronné
    Avatar de Pierre Castelain
    Inscrit en
    Avril 2002
    Messages
    523
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 523
    Points : 1 943
    Points
    1 943
    Par défaut
    Non, si tu regarde bien les déclarations, seul l'accès à l'attribut se fait en utilisant un pointeur. C'est juste une ruse qui te permet de passer le record par référence.

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

Discussions similaires

  1. properties dans classdef non modifiables avec setAccess=private
    Par oodbae_adriano dans le forum MATLAB
    Réponses: 3
    Dernier message: 01/11/2014, 15h18
  2. [SQL2K8] Attribut colonne non modifiable
    Par Theka dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 29/07/2009, 14h12
  3. [JDialog] largeur non modifiable ?
    Par lilou77 dans le forum Agents de placement/Fenêtres
    Réponses: 8
    Dernier message: 15/12/2005, 11h42
  4. Rendre un champ non modifiable sur un onclick
    Par damjal dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 12/10/2005, 01h16
  5. Réponses: 5
    Dernier message: 30/09/2005, 16h42

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