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 :

Problème de polymorphisme


Sujet :

C++

  1. #1
    Expert confirmé

    Homme Profil pro
    SDE
    Inscrit en
    Août 2007
    Messages
    2 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : SDE

    Informations forums :
    Inscription : Août 2007
    Messages : 2 013
    Points : 4 324
    Points
    4 324
    Par défaut Problème de polymorphisme
    Bonjour,

    Je suis confronté a un problème de polymorphisme, et a chaques fois que je trouve une solution ça apporterait d'autres problèmes alors je fais appel à vous.

    Voila j'ai 3 classes :
    employe,
    membre (dérivé d'employé),
    utilisateur (dérivé de membre)

    Ces classes sont persistantes, et suivent le mème modèle au niveau de la base de données.

    Chaque classe possède les méthodes suivantes :
    toEmploye(),
    toMembre(),
    toUtilisateur().

    Des instances de ces trois types différents sont stockées dans une collection.

    Ce modèle me permet a partir d'un indice dans la collection, de basculer d'un type a l'autre de manière très transparente. de ce fait, je n'ai pas a connaitre le type d'origine, je sais que la conversion sera faite sans problèmes.

    Ainsi si un utilisateur dois devenir utilisateur, il se mettra simplement à jour (avec les valeurs en paramètre ici non présentes).

    Avec ce modèle il est clair qu'un utilisateur dois impérativement être avant tout membre.
    Voici donc un cas d'utilisation :
    Un employé est sélectionne, puis on veux le transformer en utilisateur, il se passe donc :
    1/ on transforme d'abord en membre, afin de récupérer une partie des nouvelles informations spécifiques a membre.
    2/ on transforme en utilisateur avec les dernière informations.

    Maintenant on part du principe qu'un utilisateur est sélectionne :
    1/ on converti en membre, donc perte de l'information en détruisant son num de la table utilisateur.
    2/ Etant donné que c'est un utilisateur et qu'on lui demande d'en devenir un, il se mettra simplement a jour, et tentera de se modifier en base, alors qu'il viens de se supprimer.

    LA solution qui résoudrait tout serait d'éviter une appel de modification vers autres membre quand on est utilisateur, seulement dans ce cas, si on reprend l'exemple numéro un, utilisateur ne sera plus transformé en membre avant de devenir utilisateur, donc ca coincerais a ce niveau la.

    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
     
                switch(cbTypePersChoix->SelectedIndex)
                {
                case 0:
                    ((employes^)objGestListe::listEmployes[lbPers->SelectedIndex])->toTechniciens();
                    break;
                case 1:
                    ((employes^)objGestListe::listEmployes[lbPers->SelectedIndex])->toJardiniers();
                    break;
                case 2:
                    //Si en plus c'est un user alors on complète
                    ((employes^)objGestListe::listEmployes[lbPers->SelectedIndex])->toAutresMembres(newStatut);
                    if(chbUser->Checked)
                    {
                        ((employes^)objGestListe::listEmployes[lbPers->SelectedIndex])->toUtilisateurs(txtPersIdent->Text, txtPersPass->Text);
                    }
     
     
                    break;
                }
    Ici la solution serait de pouvoir savoir si l'objet sur lequel on agi est de type utilisateur, et ne pas appeler la conversion vers Membre, mais dans ce cas je perd en partie l'avantage de la polymorphie.
    Si l'un de vous à une idée.

    Je sais pas si j'ai posté au bon endroit (j'aurais peut-être du poser dans conception), si il n'est pas a la bonne place, qu'un modérateur n'hésite pas a le déplacer.
    http://alaindefrance.wordpress.com
    Certifications : SCJP6 - SCWCD5 - SCBCD5 - SCMAD1
    SDE at BitTitan

  2. #2
    Membre actif Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Points : 207
    Points
    207
    Par défaut
    Pourquoi utiliser des fonctions ToEmployee(),...

    Tu ne peux pas utiliser de cast? Si vraiment tu souhaites connaître le type à l'exécution il y a la RTTI (Run Time Type Information), mais en général dépréciée car bien souvent dû à un problème de conception et de plus peut poser des problème avec l'héritage et la polymorphie...

    Sinon tu peux simplement utiliser l'opérateur dynamic_cast :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Employe * MonEmploye = new Utilisateur();
    Utilisateur * MonUtilisateur = new dynamic_cast<Utilisateur *>(MonEmployer);
    Il me semble qu'il existe également de nouveaux opérateurs du coté de boost pour "améliorer" dynamic_cast (à voire)...
    - hp pavillon dv7
    - intel(R) Core(TM)2 Duo CPU P8400 @ 2.26GHz 2.27GHz
    - nVidia GeForce 9600M GT
    - mémoire vive : 3.0Go

  3. #3
    Expert confirmé

    Homme Profil pro
    SDE
    Inscrit en
    Août 2007
    Messages
    2 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : SDE

    Informations forums :
    Inscription : Août 2007
    Messages : 2 013
    Points : 4 324
    Points
    4 324
    Par défaut
    ces methode servent a la persistance de l'objet, ainsi a chaque fois qu'on les appellent, elles agissent sur la base de donnée afin de faire en sorte que l'instance se trouve bien dans tel ou tel table fille, et cela de façon différente en fonction du type.

    C'est pourquoi un simple cast de l'objet ne servirais a rien dans ce cas.
    La conception est peu être améliorable, mais je pense que il y a pire et que je peut en faire quelque chose.

    Je vais voir du coté du RTTI

    Merci
    http://alaindefrance.wordpress.com
    Certifications : SCJP6 - SCWCD5 - SCBCD5 - SCMAD1
    SDE at BitTitan

  4. #4
    Membre actif Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Points : 207
    Points
    207
    Par défaut
    Je viens de relire ton message ( à peu près une 50aine de fois avant de comprendre, c'est la fatigue ) Donc si j'ai bien compris le problème vient du fait que les paramètres sont différents selon si tu veux mettre à jour un employé ou un autre membre c'est bien ça? Ces paramètres sont-t-ils vraiment nécessaires lors de l'appel de ta fonction, ne peuvent-ils faire partie intégrante de la classe? Ce qui pourrait régler le problème... Essayes peut-être de bien séparer chaque tâche précise que tu dois effectuer en fonction spécifique, ça te permettra peut-être de trouver une solution mieux adaptée...
    - hp pavillon dv7
    - intel(R) Core(TM)2 Duo CPU P8400 @ 2.26GHz 2.27GHz
    - nVidia GeForce 9600M GT
    - mémoire vive : 3.0Go

  5. #5
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    J'aime bien ce type de conception. Je ne sais pas s'il possède de gros désavantages, mais je trouve qu'il a l'avantage de simplifier beaucoup l'utilisation de ces classes. On le retrouve, par exemple, dans tinyxml. Trés pratique.

    Cependant, je n'arrive pas à comprendre où est ton problème...
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  6. #6
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par r0d Voir le message
    J'aime bien ce type de conception. Je ne sais pas s'il possède de gros désavantages, mais je trouve qu'il a l'avantage de simplifier beaucoup l'utilisation de ces classes. On le retrouve, par exemple, dans tinyxml. Trés pratique.

    Cependant, je n'arrive pas à comprendre où est ton problème...
    Il possède effectivement de gros désavantages, notamment parce qu'il ne respecte pas certains des principes les plus importants de la conception OO. A terme, cela peut poser des problèmes ardu si le soft doit évoluer ou juste être maintenu.

    Puisqu'il s'agit de C++, il est toujours possible de créer des fonctions libres (hors classe) qui font le travail à la place d'une fonction membre. Exemple:

    employe* to_employe(employe *e);
    employe* to_employe(utilisateur* u);
    employe* to_employe(member* m);
    ... (etc)

    Plusieurs avantages à cette méthode :
    1) L'ajout d'une nouvelle classe dans la hierarchie ne nécessite pas la modification des classes précédemment écrites (respect du principe Open/Closed).
    2) On supprime par ce biais les dépendances circulaires (utilisateur connait membre qui connait utilisateur). On respecte ainsi le principe Acyclic Dependency Graph de R.C. Martin; on découple aussi un peu plus les classes (plus besoin d'ajouter la classe membre à un projet si on ne souhaite utiliser que la classe employe). De fait, on se simplifie la maintenance du programme.
    3) respect de la simplicité d'utilisation : la différence entre employe->to_utilisateur() et to_utilisateur(employe) est minime.

    J'ajouterai que cette solution a (à mes yeux) plus de sens que la solution originale proposée par kazou. Si on a une approche un tant soit peu ontologique, il n'est pas de la responsabilité de la classe "employe" de savoir comment se transformer en "utilisateur" - cette responsabilité doit être confiée à une autre entité.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  7. #7
    Expert confirmé

    Homme Profil pro
    SDE
    Inscrit en
    Août 2007
    Messages
    2 013
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : SDE

    Informations forums :
    Inscription : Août 2007
    Messages : 2 013
    Points : 4 324
    Points
    4 324
    Par défaut
    C'est juste. D'une façon générale je voyais bien que je me retrouverais bloquer.
    Ici je m'en sort car le projets est de petite taille, mais je sent bien que je serait limité si le programme dois grandir.
    Je vais tenter de me débrouiller dans ce sens la.
    Ce qui est certain, c'est que je ferais plus attention a la conception la prochaine fois. Je me dis toujours ça et il y a toujours un truc qui vas pas, mais c'est comme ça qu'on apprend donc ...

    Quand j'ai une solution qui marche je vous tien au courant.
    Merci de votre aide

    Kaz.
    http://alaindefrance.wordpress.com
    Certifications : SCJP6 - SCWCD5 - SCBCD5 - SCMAD1
    SDE at BitTitan

Discussions similaires

  1. Problème de polymorphisme ou de conception
    Par LinuxUser dans le forum C++
    Réponses: 16
    Dernier message: 11/12/2012, 13h07
  2. [Débutant] [POO]Problème de polymorphisme avec la méthode ToString()
    Par vmolines dans le forum C#
    Réponses: 5
    Dernier message: 08/02/2012, 00h19
  3. Problème de polymorphisme
    Par twixnoir dans le forum Langage
    Réponses: 5
    Dernier message: 06/06/2011, 23h16
  4. Réponses: 11
    Dernier message: 14/06/2010, 13h26
  5. Problème de polymorphisme
    Par oodini dans le forum Langage
    Réponses: 6
    Dernier message: 22/05/2010, 07h53

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