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

 C++ Discussion :

Exploitation du polymorphisme d'héritage lors d'une composition


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Par défaut Exploitation du polymorphisme d'héritage lors d'une composition
    Bonjour,

    J'ai l'architecture suivante :

    - classe ModelB et ModelC héritent d'une classe mère Model.
    - classe ControlerB et ControlerC héritent d'une class mère Controler.
    - classe ControlerB est composée d'un objet ModelB qu'elle contrôle.
    - classe ControlerC est composée d'un objet ModelC qu'elle contrôle.

    Est-il préfèrable de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Controler {
      public :  
        Controler();  
        ~Controler();  
        void SetModel(Model*);  
     
     protected :  
       Model* model;  
    }
    et caster le model dés que nécessaire dans les classes filles ou faire :

    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
    class Controler {
      public :  
        Controler();  
        ~Controler();  
    }
     
    class ControlerB {
      public :  
        //...
        void SetModel(ModelB*);
     
      private :
        ModelB* _model; 
    }
     
    class ControlerC {
      public :  
        //...
        void SetModel(ModelC*);
     
      private :
        ModelC* _model; 
    }
    et ne pas exploiter le polymorphisme ?

    Pour information, les modèles ModelB et ModelC sont très éloignés (Model représente un haut degrés d'abstraction) et partagent donc très peu de méthodes communes (d'ou ma question car un ControlerB ne serait par exemple pas adapté pour gérer un ModelC d'un point de vue purement logique de conception... (d'un point de vue technique, les casts permettent de résoudre ce problème)).

    Merci

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    essaye de templater la classe Controleur.
    éventuellement, rend Controleur abstraite

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Par défaut
    Merci leternel de ton aide

    éventuellement, rend Controleur abstraite
    Oui je peux même définir une interface pour le Controler.

    essaye de templater la classe Controleur.
    Mais justement, est-il judicieux de rendre générique le Controler alors que les Controlers spécifiques auront des modèles très différents (voire trop justement) pour que la logique de factorisation n'ait pas de sens ici ?

  4. #4
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Certainement, vu que tu as une interface de base.
    Qu'ils héritent de la même classe signifie qu'ils partagent la sémantique de cette classe.

    Cela se partage sûrement.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2012
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2012
    Messages : 99
    Par défaut
    Tu me conseilles donc de faire par exemple :

    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
    template<class T>
    class Controler
    {
     
    };
     
    class ControlerB : public Controler<ModelB>
    {
     
    };
     
    class ControlerB : public Controler<ModelC>
    {
     
    };
    pour éviter les casts à répétition sur un Controler qui de base aurait en membre un type abstrait Model ?
    Après, comme les modèles sont utilisés pour deux choses très différentes, la notion de template ne sera pas beaucoup plus exploitable je pense .

    Je débute en template donc j'essaie de voir ce que ça peut m'apporter en plus dans mon cas!

  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    A priori, si tu décide de faire hériter différents modèles d'une classe de base, c'est que tu as sans doute une interface minimum commune.

    Si tu choisi de placer le modèle ("de base") dans la classe de base "controler", tu ne pourras profiter utiliser ton modèle au travers de ton contrôleur que... sous la forme sous laquelle le contrôleur le connais, à savoir : le modèle "de base".

    Maintenant, rien ne t'empêche de prévoir une fonction virtuelle (pure, dans le modèle de base) qui prenne un "indice" en argument et qui renvoie, d'une manière ou d'une autre, la valeur correspondant à cet indice. Tu pourrais donc, pour chaque modèle particulier, redéfinir cette fonction de manière à ce qu'elle fournisse une valeur "cohérente".

    Pour pouvoir travailler "facilement", la valeur renvoyée serait sans doute du genre de boost::any ou boost::variant

    Une autre solution pourrait consister à utiliser ce que l'on appelle le "retour co-variant".

    L'idée étant, dans la classe de base de contrôleur, de déclarer une fonction virtuelle pure renvoyant un pointeur sur le modèle de base, et de la redéfinir, dans les classes dérivées, de sorte à ce qu'elle renvoie un pointeur sur le modèle spécifique géré par ton contrôleur.

    Tu peux alors envisager les deux solutions : le fait de maintenir ce pointeur au niveau de la classe de base contrôleur, en redéfinissant la fonction sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ModeleDerive * ControleurDerive::model(){return dynamic_cast<ModeleDerive>(Controler::model());}
    tout comme tu pourrais tout aussi bien considérer que le modèle spécifique est une information qui ne doit pas être maintenue au niveau de la classe de base des contrôleurs, mais qui doit être maintenue au niveau de leurs classes dérivées.

    Il n'y a, à ce niveau, ni "bonne" ni "mauvaise" décision, dans le sens où elles seraient toutes les deux parfaitement cohérentes.

    Cependant, on dit souvent qu'un interface ne devrait disposer que des données strictement minimales pour fournir les comportements "immuables" (ceux qui n'ont en aucun cas vocation à être redéfinis ).

    Or, tous les comportements ayant trait à la gestion du modèle a, j'ai envide de dire forcément, vocation à être redéfinis.

    Il serait donc sans doute "de bon ton" de faire en sorte que le modèle particulier géré par un contrôleur particulier ne soit contenu que dans ce contrôleur particulier (mais ce n'est qu'un avis strictement personnel).

    Par contre, je ne crois sincèrement pas qu'il soit opportun de fournir un mutateur "setModel":

    D'abord, parce que le prototype de ce mutateur serait "figé" et prendrait d'office un Model * au lieu d'un ModelParticulier *

    Ensuite parce que l'idéal est à mon sens d'avoir un contrôleur directement utilisable dés la construction: une fois que tu as créé une instance de contrôleur, tu ne devrais avoir rien d'autre à faire pour pouvoir l'utiliser.

    De plus, il y a de fortes chances pour que, si tu veux travailler avec un autre modèle, il faille... travailler avec un autre contrôleur.

    Tout cela pour dire que, à mon sens, tu devrais sans doute t'orienter vers quelque chose qui serait proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Controler
    {
        /* les fonctions virtuelles pures "qui vont bien" */
    }
    class ControlerB : public Controler
    {
        public:
            ControlerB(ModelB* model):model_(model){}
            /* redéfinition des fonction qui vont bien */
        private:
            ModelB * model_;
    };
    NOTA: si tu prend cette direction, tu pourrais d'ailleurs tout à fait travailler avec des références (éventuellement constantes) plutôt qu'avec des pointeurs, ce qui devrait encore te faciliter la tâche
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 19/12/2006, 14h08
  2. Mauvais noms de colonnes lors d'une requête
    Par nmathon dans le forum Bases de données
    Réponses: 2
    Dernier message: 09/04/2004, 07h27
  3. Combler les trous lors d'une suppression dans une table
    Par Billybongjoe dans le forum PostgreSQL
    Réponses: 5
    Dernier message: 08/04/2004, 14h02
  4. Erreur lors d'une requete INNER JOIN
    Par k-lendos dans le forum Langage SQL
    Réponses: 2
    Dernier message: 17/03/2004, 15h09
  5. Enlever la surbrillance lors d'une recherche avec vi
    Par sekiryou dans le forum Applications et environnements graphiques
    Réponses: 8
    Dernier message: 04/03/2004, 13h55

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