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 :

Ecriture d'une fonction de vérification d'une valeur d'un objet


Sujet :

Langage Delphi

  1. #1
    Inactif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    97
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 97
    Points : 84
    Points
    84
    Par défaut Ecriture d'une fonction de vérification d'une valeur d'un objet
    Bonjour,

    J'ai un petit problème phylosophique avec Delphi. Voici mon problème :

    Soit une classe définie par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    TLambda = class
      private
        fValeur: Integer;
        function  getValeur: Integer;
        procedure setValeur(Valeur: Integer);
      public
        Property Valeur   : Integer read getValeur write setValeur;
        constructor Create;
      end;
    Dans ma procédure setValeur, je voudrais appeler une fonction isValide qui me permet de :
    - Mettre fValeur à Valeur si isValide retourne vrai
    - Garder fValeur à sa valeur précédente si isValide retourne faux

    Le problème, c'est que je ne sais pas comment définir isValide.

    1. Est-ce une fonction private? Dans ce cas, doit-elle prendre un argument ou doit-elle tester la variable fValeur ?
    2. Est-ce une fonction public ? Même question que pour private
    3. Doit-elle être une fonction extérieure à l'objet ? Dans ce cas, ça me gêne un peu car isValide ne servirait qu'à l'objet. Comme il ne sert que dans ce cadre, ça me gêne un peu de le déclarer à l'extérieur de l'objet.

    J'ai un exemple de code, mais la solution utilisée est la 3. Ca me gêne, car, pour moi, la logique 'métier' de l'objet doit appartenir à l'objet.

    Pouvez vous répondre à cette simple question ?

    Merci.

    Bonne année à tous

    Philippe.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 832
    Points : 13 582
    Points
    13 582
    Par défaut
    Tu ne peux pas tester fValeur si cette variable ne doit être modifiée que dans certains cas . Donc un argument est obligatoire à IsValid.

    Le choix de private (voir protected si ce test est susceptible d'évoluer dans une classe dérivée) ou public ne depend que de ton implémentation. Est-ce qu'il est strictement interne à ta classe ou peut-il être utile de l'invoquer depuis l'extérieur ?

    Dans tout les cas, le mettre au départ en private et le déplacer le cas échéant n'est pas interdit .

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 713
    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 713
    Points : 25 605
    Points
    25 605
    Par défaut
    le Setter setValeur sert justement à mettre les conditions de modification de Valeur, je ne vois pas trop l'intérêt de découper en deux fonctions à moins qu'il soit très complexe.
    Sinon, tu as déjà répondu à la question

    Dans ce cas, ça me gêne un peu car isValide ne servirait qu'à l'objet. Comme il ne sert que dans ce cadre, ça me gêne un peu de le déclarer à l'extérieur de l'objet.
    Il ne sert qu'à l'objet, donc private et tu lui passe en paramètre la nouvelle valeur (comme setValeur et renvoie un boolean)

  4. #4
    Membre éclairé Avatar de peter27x
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 029
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 029
    Points : 757
    Points
    757
    Par défaut
    Je vois pas quel est ton problème.

    Tu mets fValide en private, et tu l'appeles depuis setValeur... où est le pb ?

  5. #5
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    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
    type
      TLambda = class
      private
        fValue: Integer;
        procedure setValue(Value: Integer);
      protected
        function IsValid(const Value: integer): boolean; dynamic;
      public
        property Value : Integer read fValue write setValue default 0;
        constructor Create;
      end;
     
     
    constructor TLambda.Create;
    begin
      fValue := 0;
    end;
     
    function TLambda.IsValid(const Value: integer): boolean;
    begin
      result :=  ((Value >= 0) and (Value <= 100)) and (Value <> fValue);
    end;
     
    procedure TLambda.setValue(Value: integer);
    begin
      if IsValid(Value) then
        fValue := Value;
    end;

  6. #6
    Inactif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    97
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 97
    Points : 84
    Points
    84
    Par défaut Merci à tous !
    Un grand merci à tous pour vos réponses !

    C'est nickel !

    Mais là où j'ai vraiment compris, c'est grâce à Dr. Who:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TLambda.setValue(Value: integer);
    begin
      if IsValid(Value) then
        fValue := Value;
    end;
    En fait, je m'imaginais, à tort, que l'utilisation de IsValid ne pouvait se faire que par

    Ce qui me gênait quelque peu...

    Mais ce code est parfait et lève tous mes doutes !

    En tous cas, je vous réitère à tous un grand merci pour votre aide !

    A+

    Philippe.

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 713
    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 713
    Points : 25 605
    Points
    25 605
    Par défaut
    Euh, le Self est implicite dans le code du Dr. Who, le Self c'est l'instance en cours ... je ne vois pas en quoi cela te pose problème

    Self peut être aussi la Classe si c'est une méthode de classe et non une méthode d'instance mais j'ignore comment cela fonctionne avec les propriétés de classe, je n'ai que D7

  8. #8
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    Self fait référence à l'instance en cours de la classe.

    c'est un mot clef de la programmation abstraite.

    il permet de pouvoir assigner une instance de classe sans connaitre l'identifiant de cette dernière.

    on utilisera par exemple Self pour les constructeur, les methode de référencement (FreeNotification, RemoveFreeNotification par exemple) ou encore les methode d'assignation (Assign, AssignTo par exemple).

    On trouve souvent l'erreur dans les codes de débutant ou dans les fiches on trouve plus souvent d'appel à la variable de l'instance de la fiche (Form1 par exemple) plutot qu'a Self.

    exemple d'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Composant := TComponent.Create(Form1);
      Form1.Tag := Form1.Tag + 1;
    end;
    exemple bon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure TForm1.Button1Click(Sender: TObject);
    var Composant : TComponent;
    begin
      Composant := TComponent.Create(Self);
      Composants.Add(Composant); // TObjectList
      Self.Tag := Self.Tag + 1;
    end;
    exemple parfait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      Composants.Add( TComponent.Create(Self) ); // TObjectList
      inc(Tag);
    end;

  9. #9
    Inactif
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    97
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 97
    Points : 84
    Points
    84
    Par défaut Qu'appelles-tu erreur ?
    @ShaiLeTroll
    Ca me posait problème car j'imaginais qu'un appel à une méthode ne pouvait se faire que par xxxx.Methode (où xxxx peut être self)
    Mais, en fait, tu as raison : ça ne devrait pas me gêner

    @Dr.Who
    Qu'appelles-tu 'erreur' dans la première implémentation ?
    1. Quelque chose qu'il est préférable de ne pas faire car générant une erreur si on change le nom de la TForm
    2. Ou quelque chose qui ne compile pas, voire pire, qui induit un bug dans l'application ?

    Merci !

  10. #10
    Membre éprouvé
    Avatar de Dr.Who
    Inscrit en
    Septembre 2009
    Messages
    980
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Septembre 2009
    Messages : 980
    Points : 1 294
    Points
    1 294
    Par défaut
    alors :

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    Composant := TComponent.Create(Form1);
    Form1.Tag := Form1.Tag + 1;
    end;


    la variable Form1 fait reference à une et une seule instance de TForm1.

    si l'on utilise TForm1 à des fin particulière (multi fiches) avec des creations dynamique de TForm1, le code vas généré un bug de fonctionnement.
    car les valeurs de l'instance Form1 ne corresponderont pas aux valeurs des instances necessaires au fonctionnement du logiciel.

    par exemple Form1A et Form1B devront être différent, mais si TForm1 fait appel à Form1 dans son code, alors Form1A et Form1B ne pourront pas avoir de valeurs propres à elles puisque irrémédiablement dépendante des valeurs de Form1.

    sans parler du fait, que si Form1 n'est pas instancié, il y aura une erreur de violation d'accés dans Form1A et Form1B.

    la est l'erreur, donc, ne jamais utiliser la variable FormX dans un code.
    toujours utiliser Self ou utiliser un paramètre de type TForm pour les fonctions externes à la classe.

    exemple d'une procedure externe fausse :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure SetCaption;
    begin
      Form1.Caption := 'Bonjour';
    end;
     
    procedure TForm1.Form1Create(Sender: TObject);
    begin
      SetCaption;
    end;

    exemple corrigé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure SetCaption(aForm : TForm);
    begin
      aForm.Caption := 'Bonjour';
    end;
     
    procedure TForm1.Form1Create(Sender: TObject);
    begin
      SetCaption(Self);
    end;

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

Discussions similaires

  1. une fonction en entrée d'une fonction
    Par lefevrelaumonier dans le forum MATLAB
    Réponses: 3
    Dernier message: 24/12/2011, 04h36
  2. Passer une Fonction comme argument d'une fonction
    Par ch16089 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 27/02/2011, 18h58
  3. Réponses: 3
    Dernier message: 16/04/2009, 09h34
  4. [Langage] une fonction comme argument d'une fonction?
    Par Krishna dans le forum Langage
    Réponses: 9
    Dernier message: 15/10/2008, 21h31
  5. passage d'une fonction en parametre d'une fonction
    Par psylox dans le forum Langage
    Réponses: 5
    Dernier message: 06/10/2008, 17h40

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