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 :

Descendants ou Méthodes, comment s'y prendre


Sujet :

Langage Delphi

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2009
    Messages : 322
    Points : 310
    Points
    310
    Par défaut Descendants ou Méthodes, comment s'y prendre
    Bonjour

    Je dois appeler une méthode spécifique d'évaluation selon l'initialisation, soit la lecture d'un fichier dont chaque ligne correspond à un traitement séparé, indépendant et répétitif , lors de l'exécution du programme.

    J'ai deux possibilités

    1) Soit je crée une class Racine dont je ferai hériter deux classes Assis et Debout

    2) Soit je crée un type procedural générique et c'est la class Racine qui se charge de choisir à l'initialisation soit la procedure Assis et Debout (même destination que les classes ci-dessus)

    Dans les deux cas, je vois mal comment gérer cela sans faire ~ l'écriture suivante dans le programme principal
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    var ListeDeClasse:tstringlist;
    ...
    function Evaluation(X:integer):Boolean;
    begin
    if ListeDeClasse[X]='Assis' then  result:=(ListeDeClasse.Objects[X]as oClasseAssis).evaluation else
    if ListeDeClasse[X]='Debout' then result:=(ListeDeClasse.Objects[X]as oClasseDebout).evaluation else
        ... 
    end;
    C'est n'est pas propre et pour la maintenance ce n'est pas de la tarte si j'ai plusieurs programmes à maintenir... et plusieurs routines d’évaluation distinctes à coder... etc.

    Alors comment faire ça proprement à l'initialisation afin de pouvoir écrire simplement dans le programme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
       result:=CetObjetInconnuALaCompilation.evaluation;
    Merci d'avance

  2. #2
    Membre expérimenté
    Avatar de retwas
    Homme Profil pro
    Développeur Java/Delphi
    Inscrit en
    Mars 2010
    Messages
    698
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Java/Delphi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 698
    Points : 1 608
    Points
    1 608
    Billets dans le blog
    4
    Par défaut
    Avec une interface ou tu ajoutes une méthode Execute.

    Et dans la procédure tu passes une classes du type de l'interface après peux importe d'avoir un TDebout ou un TAssis tu appelles le Execute.

  3. #3
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 455
    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 455
    Points : 24 867
    Points
    24 867
    Par défaut
    On part de ton code avec trois classes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var ListeDeClasse:tstringlist;
    ...
    function Evaluation(X:integer):Boolean;
    begin
    if ListeDeClasse[X]='Assis' then  result:=(ListeDeClasse.Objects[X]as oClasseAssis).evaluation else
    if ListeDeClasse[X]='Debout' then result:=(ListeDeClasse.Objects[X]as oClasseDebout).evaluation else
    if ListeDeClasse[X]='Couché' then result:=(ListeDeClasse.Objects[X]as oClasseCouche).evaluation else
        ... 
    end;
    Bizarre, vu le code tu pourrais faire plus simple

    oClasseAssis, oClasseDebout et oClasseCouche hérite oClassePosition

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    oClassePosition = class
      function evaluation(): Boolean; virtual; abstract;
    end;
     
    oClasseAssis= class
      function evaluation(): Boolean; override;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ListeDeClasse.Add('Assis', oClasseAssis.Create);
    ListeDeClasse.Add('Debout', oClasseDebout.Create);
    ListeDeClasse.Add('Couché', oClasseCouche.Create);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    function Evaluation(const APositionName: string):Boolean;
    var
      X: Integer;
    begin
      X := ListeDeClasse.IndexOf(APositionName);
      Result := (X >= 0) and oClassePosition(ListeDeClasse.Objects[X]).evaluation;
    end;

    tu le faire avec un simple array of TClass si la liste est finie ou une TClassList si il peut y en avoir beaucoup et que la liste est variable

    Voici la variante

    array of TClass

    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
     
    type
      TMachinType = (mtTruc, mtBidule, mtChose);
     
    const
      Machin_NAMES: array[TMachinType] of string = ('Truc', 'Bidule', 'Chose');
     
    const
      Machin_CLASSES: array[TMachinType] of TClass = (TObjectTruc, TObjectBidule, TObjectChose);
     
     
    class function TMachinManager.GetEchantMachin(const MachinName: string): TClass;
    var
      iMachin: TMachinType;
    begin
      for iMachin := Low(TMachinType) to High(TMachinType) do
      begin
        if SameText(MachinName, Machin_NAMES[iMachin]) then
        begin
          Result := Machin_CLASSES[iMachin];
          Exit;
        end;
      end;
     
      Result := nil;
    end;

    La Variante TClassList
    j'aurais tendance à éviter le class pour y mettre un singleton pour le Manager et une Factory pour les Position mais class c'est plus rapide à écrire
    Au final, c'est une pattern Strategy !


    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
    type
      TPosition = class(TObject)
      protected
        class function GetPositionName(): string; virtual; abstract;
      public
        class function Evaluation(): Boolean; virtual; abstract;
        class property PositionName: string read GetPositionName;
      end;
     
      TPositionClass = class of TPosition;
     
      TPositionManager = class(TObject)
      private
        class var FList: System.Contnrs.TClassList;
      public
        class procedure RegisterPosition(APositionClass: TPositionClass);
        class function FindPosition(const APositionName: string): TPositionClass;
      public
        class constructor Create();
        class destructor Create();
      end;
     
     
    //------------------------------------------------------------------------------
    class constructor TPositionManager.Create();
    begin
      FList := System.Contnrs.TClassList.Create();
    end;
     
    //------------------------------------------------------------------------------
    class destructor TPositionManager.Destroy();
    begin
      FreeAndNil(FList);
    end;
     
    //------------------------------------------------------------------------------
    class procedure TPositionManager.RegisterPosition(APositionClass: TPositionClass);
    begin
      FreeAndNil(FList);
    end;
     
    //------------------------------------------------------------------------------
    class function TPositionManager.FindPosition(const APositionName: string): TPositionClass;
    begin
      for I := 0 to FList.Count - 1 do 
        if FList[I].PositionName = APositionName then
          Exit(FList[I]);
     
      Result := nil;
    end;
    après tu peux avoir un tas de TPosition déclaré dans d'autres unités ... c'est comme le FindClass de Delphi
    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

  4. #4
    Membre expérimenté
    Avatar de retwas
    Homme Profil pro
    Développeur Java/Delphi
    Inscrit en
    Mars 2010
    Messages
    698
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Java/Delphi
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 698
    Points : 1 608
    Points
    1 608
    Billets dans le blog
    4
    Par défaut
    En complément de la solution de Shail, un petit exemple avec les interfaces

    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    type
       TTypePosition = (tpDebout, tpAssis, tpCoucher);
     
       IPosition = interface
       ['{0EE045A9-E8D3-4702-8F66-8A4D2B488156}']
          function Evaluation: boolean;
          function GetTypePosition: TTypePosition;
       end;
     
       TPositionDebout = class(TInterfacedObject, IPosition)
          function Evaluation: boolean;
          function GetTypePosition: TTypePosition;
       end;
     
       TPositionAssis = class(TInterfacedObject, IPosition)
          function Evaluation: boolean;
          function GetTypePosition: TTypePosition;
       end;
     
       TListPosition = class(TList<IPosition>)
          function Evaluation(aTypePosition: TTypePosition): boolean;
       end;
     
     
    { TPositionDebout }
     
    function TPositionDebout.Evaluation: boolean;
    begin
       Writeln('Je suis debout.');
       Result := True;
    end;
     
    function TPositionDebout.GetTypePosition: TTypePosition;
    begin
       Result := tpDebout;
    end;
     
    { TPositionAssis }
     
    function TPositionAssis.Evaluation: boolean;
    begin
       Writeln('Je suis assis.');
       Result := True;
    end;
     
    function TPositionAssis.GetTypePosition: TTypePosition;
    begin
       Result := tpAssis;
    end;
     
    { TListPosition }
     
    function TListPosition.Evaluation(aTypePosition: TTypePosition): boolean;
    var
       i: integer;
    begin
       Result := False;
     
       for i := 0 to Count - 1 do
       begin
          if Self[i].GetTypePosition = aTypePosition then
          begin
             // execute la procédure du type correspondant au TypePosition
             Result := Self[i].Evaluation;
             Exit;
          end;
       end;
    end;
     
    var
       ListPosition: TListPosition;
       iCount       : integer;
    begin
       try
          try
             ListPosition := TListPosition.Create;
             ListPosition.Add(TPositionDebout.Create);
             ListPosition.Add(TPositionAssis.Create);
     
             for iCount := 0 to ListPosition.Count - 1 do
                ListPosition[iCount].Evaluation;
     
             Readln;
          finally
             FreeAndNil(ListPosition);
          end;
       except
          on E: Exception do
             Writeln(E.ClassName, ': ', E.Message);
       end;
    end.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    322
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2009
    Messages : 322
    Points : 310
    Points
    310
    Par défaut
    Merci pour vos réponses.

    Voici, ce que je tente de faire, ça compile, (je vais finir de coder pour voir si ça fonctionne réellement) (maintenant je ne suis plus certain que ça compile car j'ai simplifié en expliquant le 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
    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
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    type
    oObjetCommande=class
    ....
    end;
     
    fEvaluation:function(StrategieSpecifique:tObject):boolean of object;
     
    oObjetConteneur=class
    private
        vStrategie:tObject;
    protected   
        Commande:oCommande;    //La strategie modifiera cette variable 
        Etat:string;           //Idem
        MessageReussite:string;//  "  à l'initialisation
        Reussite:boolean;      //  " à l'initialisation
        LigneStrategiqueDecortiquee:tstringlist;//Sert à faire le traitement spécifique
        EvaluationCachee:fEvaluation;
    public
        constructor create(LigneDeStrategie:String;Reference:integer);
        function Evaluation(Commande:oCommande;var Etat:string):boolean;
    end;
     
    oObjetStrategie=class
    private
        vObjetConteneur:oObjetConteneur;    
        function EvaluationSpecifique:(StrategieSpecifique:tObject):boolean
    public
        ParametreA,ParametreB,ParametreC:string;//peut importe
        constructor create(ObjetConteneur:oObjetConteneur);//La class a accès au données du conteneur
    end;
     
    implementation
     
    constructor oObjetConteneur.create(LigneDeStrategie:String;Reference:integer);
    begin
    //Decortique la ligne Strategique et fait le traitement nécéssaire à ce niveau;
        LigneStrategiqueDecortiquee:=...
    //Appel l'objet strategique approprié
        if NomDeStrategie='Debout' then vStrategie:=oStrategieDebout.create(Self) else
        if NomDeStrategie='Assis' then ...
     
    end;
    function oObjetConteneur.Evaluation(Commande:oCommande;var Etat:string):boolean;
    begin
         result:=vStrategie.EvaluationSpecifique(vStrategie);
         Commande:=Self.Commande;
         Etat:=Self.Etat;
    end;
     
    oObjetStrategie=class
    private
        ObjetConteneur:oObjetConteneur;    
     
    function oObjetStrategie.EvaluationSpecifique:(StrategieSpecifique:tObject):boolean;
    begin
        if StrategieSpecifique.ParametreA then begin
            ...
        end;
    end;
     
    constructor oObjetStrategie.create(ObjetConteneur:oObjetConteneur);//La class a accès au données du conteneur
    begin
        ObjetConteneur.Reussite:=true;
    // Continue le traitement spécifique
        ...
        if not ObjetConteneur.Reussite then exit;
    //Fait les liens avec l'objet conteneur
        ObjetConteneur.EvaluationCachee=EvaluationSpecifique;
     
    end;
    Au final, c'est l'objet conteneur qui fait l'interface... Donc ça reste transparent au programme, quelque soit la façon que c'est programmé. Sauf dans la solution proposé ici, si il y a un problème de conception c'est l'enfer à maintenir, surtout après quelque mois

    Donc aussi bien faire comme je proposais au départ et améliorer avec vos suggestions retwas et ShaiLeTroll

    Merci et désolé pour le dérangement.

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

Discussions similaires

  1. [LDAP] comment s'y prendre pour faire une recherche complexe
    Par dervish dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 10/03/2006, 14h56
  2. [MySQL] Comment s'y prendre pour une expiration après deux jours ?
    Par isa150183 dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 21/01/2006, 20h36
  3. MySQL sous linux comment s'y prendre?
    Par Doberman dans le forum Débuter
    Réponses: 4
    Dernier message: 10/01/2006, 11h58
  4. Site multilingue : comment s'y prendre ?
    Par sg-40 dans le forum Général Conception Web
    Réponses: 3
    Dernier message: 26/04/2005, 14h40
  5. Webbrowser : Comment ne pas prendre la page en cache
    Par cedm78 dans le forum Web & réseau
    Réponses: 3
    Dernier message: 30/08/2002, 11h17

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