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 :

Accesseur / Mutateur


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Accesseur / Mutateur
    Bonjour,

    Voila je suis nouveau sur le forum, j'ai épluché un peu le site à la recherche d'infos sur ce sujet, j'ai obtenu des infos intéressantes mais des questions subsistes.

    Voici un petit exemple qui illustre mes interrogations :
    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
     
    class CRoue
    {
    private:
        float m_fDiametre;
    public:
        const float & GetDiametre() const;
        void SetDiametre(cont float & fDiametre);
    }
     
    class CVoiture
    {
    private:
        CRoue m_roue;
     
    public:
        const CRoue & GetRoue() const;
    }
    peut on remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const float & GetRoue() const;
    par :
    ainsi on peut appliquer le mutateur SetDiametre() directement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void main()
    {
        CVoiture voiture;
        voiture.GetRoue().SetDiametre(500.0);
    }
    Ou faut il garder :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    const float & GetRoue() const;
    et créer le mutateur du diamètre de la roue directement dans la classe CVoiture? :
    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
     
    class CVoiture
    {
    private:
        CRoue m_roue;
     
    public:
        const CRoue & GetRoue() const;
        void SetDiametreRoue(const float & fDiametre);
    }
     
    void CVoiture::SetDiametreRoue(const float & fDiametre)
    {
        this->m_roue.SetDiametre(fDiametre);
    }
     
    void main()
    {
        CVoiture voiture;
        voiture.SetDiametreRoue(500.0);
    }
    Un accesseur n'est pas censé modifier la donnée qu'il retourne mais peut il retourner un pointeur sur cette donnée pour que celle ci soit modifiée?
    Sinon, doit on développer des mutateurs dans chaque classe contenant l'objet à modifier (ex : SetDiametre() et SetDiametreRoue() un mutateur par classe) ? Ceci alourdit le code, y'a t'il une autre solution?

    Voila, j'espère avoir été clair
    Merci d'avance

  2. #2
    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
    Bonjour,

    pour ma part, je pense que c'est une question presque philosophique, et au moins sémantique. Je m'explique:
    Si une fonction porte le nom GetX(), cela signifie: donne-moi la valeur de la variable x, étant sous-entendu que c'est seulement pour connaitre cette variable, et non dans le but de la modifier. En effet, si on veut modifier cette variable, on utilsera plutot un modificateur (setter) du style: SetX( float nouvelle_valeur );

    Enfin, si tu souhaites que ta variable membre x puisse être modifiée par "tout le monde", alors pourquoi ne pas directement la mettre en public? Certes cela rompt l'encapsulation, mais ce n'est pas forcément mal, et puis de toutes façons, si tu as un accesseur qui renvoie une référence non constante vers cet objet, cela rompt également l'encapsulation.

    C'est mon point de vue. Moi je n'hésite plus à déclarer en public des variables membre lorsqu'il n'y a pas de raison pour qu'elles ne le soit pas.
    « 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

  3. #3
    Membre actif
    Homme Profil pro
    Consultant BigData
    Inscrit en
    Juillet 2009
    Messages
    129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Consultant BigData

    Informations forums :
    Inscription : Juillet 2009
    Messages : 129
    Points : 280
    Points
    280
    Par défaut
    Je pense également qu'il s'agit ici plus d'une question de sémantique.

    Ce qu'il faut se poser comme question, c'est "est-ce que ma classe englobante doit avoir connaissance du paramètre de la classe englober ?" J'entend par là que plusieurs méthodes sont à mon avis toutes aussi valables les unes que les autres suivant le contexte.

    Dans ton cas, je trouve que d'ajouter une méthode setDiametreRoue dans CVoiture est une idée tout à fait correcte. Elle va juste englober un appel à m_roue.SetDiametre(...).

    Par contre, enlever le const sur un getter est, de mon point de vue, une pratique à éviter. De façon général, si on demande à obtenir une valeur, on ne demande pas à la modifier.

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Tout d'abord merci

    Vos réponses m'éclairent un peu sur le sujet, mais je ne peut m'empêcher de penser que d'un côté, si je fait un mutateur sur chaque classe englobante on va atteindre un nombre hallucinant de méthodes dans la classe qui englobe toutes les autres.
    Et d'un autre côté, je me dis que rompre l'encapsulation n'est pas une bonne chose.
    Un compromis entre les deux me pousserais à respecter l'utilisation d'accesseurs et de mutateurs pour les variables membres de types communs, int, float, bool... et mettre les variables membres étant des classes complexes en public.

    J'ai bien retenu la question à se poser :
    est-ce que ma classe englobante doit avoir connaissance du paramètre de la classe englober ?
    La plus part du temps dans mon cas c'est oui, c'est donc peut être dû à un mauvais découpage des classes dès le début de la conception .

    En tout cas merci pour vos réponses

  5. #5
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par VanLoc Voir le message
    Vos réponses m'éclairent un peu sur le sujet, mais je ne peut m'empêcher de penser que d'un côté, si je fait un mutateur sur chaque classe englobante on va atteindre un nombre hallucinant de méthodes dans la classe qui englobe toutes les autres.
    Et d'un autre côté, je me dis que rompre l'encapsulation n'est pas une bonne chose.
    En mettant des accesseurs/mutateurs sur tous les membres de ta classe (surtout s'ils sont triviaux), tu romps déjà l'encapsulation. Conceptuellement,que tu puisses accéder à tous les membres de ta classe car ils sont public ou car il existe un mutateur sur chacun d'entre eux cela ne change pas grand chose.

    Raisonne sur les services qu'offrent la classe plutôt que sur les données qui la composent.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    Je rejoins gl dans mon approche...

    Normalement, les membres d'une classe devraient surtout être utilisés pour permettre à la classe de rendre les services que l'on attend d'elle...

    Dans le cas présent, il faut te poser la question de savoir quelle service tu attend que ta classe Roue puisse te rendre grâce à son membre diamètre.

    Une chose est sure, c'est que si tu peux effectivement attendre qu'elle soit en mesure de répondre à la question "quel est ton diamètre", il n'y a, a priori, aucune raison de pouvoir le modifier...

    Si tu change le diamètre d'une roue, tu obtiens, purement et simplement, une autre roue
    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

  7. #7
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Raisonne sur les services qu'offrent la classe plutôt que sur les données qui la composent.
    Je rejoind aussi gl sur ce point.

    Lorsque tu concois ta classes, dans un premier temps tu n'as pas à t'occuper des données, elles n'ont aucunes importance. Par contre tu devrais te demander, qu'est ce que doit offrir ma classe comme services ? En gros : quel est l'interface publique (l'ensemble des fonctions/type/attributs publiques). Si tu n'arrives pas à répondre à cette question ou que la réponse que tu apportes est floue c'est que ta classe n'est pas encore utile ou que tu n'as pas encore bien définie sa responsabilité au sein de ton code.

    Lorsque tu as définies les services quelle doit rendre, alors les données à mettre derière seront un choix assez indépendant, tu pourras dans un premier temps utiliser une certaines représentation des données et ensuite une autre. Par exemple si tu codes une classe qui va en interne utiliser un conteneur, tu vas peut-etre dans un premier temps penser utiliser un vector, puis ensuite te rendre compte qu'utiliser une liste serait plus performente dans ce cas, mais il n'y a pas de raison que ce choix impacte l'interface de ta classe !

    Pour les mutateurs/accesseurs, si ils rendent un vraie service alors leur présence peut-etre justifiées, sinon ils ne font que rompre l'encapsulation et créer une certaine dépendance entre l'interface et la représentation des données.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Pour les mutateurs/accesseurs, si ils rendent un vraie service alors leur présence peut-etre justifiées, sinon ils ne font que rompre l'encapsulation et créer une certaine dépendance entre l'interface et la représentation des données.
    Et surtout, ils ont la détestable tendance à contrevenir à la loi demeter:

    Si une classe A utilise (comme membre interne) un objet de la classe B et qu'une classe C utilise (comme membre interne ou comme argument donné à une fonction) la classe A, il n'y a, a priori, aucune raison pour que C ait connaissance de l'existence de B
    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

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Février 2011
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2011
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Merci pour vos réponses,

    Il est vrai que quand je conçois une classe je pense d'abord aux attributs qu'elle va avoir et ensuite j'ajoute les méthodes pour manipuler ces attributs.
    Donc je dois changer ma façon de concevoir des classes

  10. #10
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Je rejoins Koala et gl et j'ajoute que dans certains cas, l'utilisation de friend peut résoudre des problèmes d'encapsulation.

    Bien entendu, ça ne te dispense aucunement de concevoir tes classes correctement.
    Find me on github

  11. #11
    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 VanLoc Voir le message
    Merci pour vos réponses,

    Il est vrai que quand je conçois une classe je pense d'abord aux attributs qu'elle va avoir et ensuite j'ajoute les méthodes pour manipuler ces attributs.
    Donc je dois changer ma façon de concevoir des classes
    C'est ce qui arrive lorsqu'on pense à ses objets en se mettant à leur place : "qu'es-ce que je suis ? de quoi suis-je fait ?". C'est une approche dite ontologique (de ontologie : étude de l'être en se plaçant à la place de l'être). Ce n'est pas une mauvaise approche dans certains cas, mais elle est clairement limitée. Une approche plus inétressante consiste à répondre à la question : "quels services est-ce que je rends ?", car c'est la réponse à cette question, au final, qui permet de définir une interface.

    C'est un sujet super intéressant à débattre, et je ne serais pas contre savoir quelle approche les autres membres de ce forums utilisent, et s'ils ont réflechi en profondeur à cette question (par exemple, l'approche UML (définition des cas d'utilisation, réalisation des diagrammes de robustesse, création des diagrammes de classe) même assez souvent vers une approche ontologique - est-ce mal ? est-ce suffisant ? etc).
    [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.

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    C'est un sujet super intéressant à débattre, et je ne serais pas contre savoir quelle approche les autres membres de ce forums utilisent, et s'ils ont réflechi en profondeur à cette question (par exemple, l'approche UML (définition des cas d'utilisation, réalisation des diagrammes de robustesse, création des diagrammes de classe) même assez souvent vers une approche ontologique - est-ce mal ? est-ce suffisant ? etc).
    Je suis du genre à réfléchir aux services attendus, en me basant sur une analyse des besoins (use case, entre autre) et en essayant d'appliquer quelques principes / lois / règles de conception (demeter, LSP, SRP, ...)
    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

  13. #13
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Points : 1 543
    Points
    1 543
    Par défaut
    Salut,

    Citation Envoyé par Emmanuel Deloget Voir le message
    C'est un sujet super intéressant à débattre, et je ne serais pas contre savoir quelle approche les autres membres de ce forums utilisent.
    Je fais du TDD (avec des mock objects) et j'ai banni les accesseurs et mutateurs.
    C'est la théorie bien sûr, en pratique ça dépend du domaine (code métier ou bibliothèque générique) et surtout de l'environnement (boulot à plein ou open-source à peu voire seul).
    Mais je trouve assez magique comme le TDD fait couler de source un peu tout le reste, dont tous ces principes qu'on tente de transmettre sous forme d'axiomes.

    Mais oui, services-push bien, données-pull mal !

    L'UML c'est bien pour gribouiller sur une nappe au resto, comme ça on peut se laver les mains après...

    MAT.
    (quitte à y aller franchement...)

  14. #14
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par Mat007 Voir le message
    L'UML c'est bien pour gribouiller sur une nappe au resto, comme ça on peut se laver les mains après...
    Je ne suis donc pas le seul à le penser, ça fait plaisir
    Find me on github

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

Discussions similaires

  1. Intérêt de l'accesseur /mutateur ?
    Par orphee03 dans le forum Débuter avec Java
    Réponses: 6
    Dernier message: 30/08/2013, 17h12
  2. [NetBeans 6.9] probleme accesseurs-mutateurs
    Par stc074 dans le forum NetBeans
    Réponses: 0
    Dernier message: 31/10/2010, 16h33
  3. Mutateur et accesseur sur énumération
    Par stallaf dans le forum Débuter
    Réponses: 13
    Dernier message: 17/08/2010, 13h44
  4. [Doc] Mutateurs/Accesseurs PHP5, comment faites vs ?
    Par ePoX dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 28/02/2006, 01h34
  5. Outils pour creer les accesseurs et les mutateurs
    Par MarieMtl dans le forum MFC
    Réponses: 3
    Dernier message: 03/10/2005, 17h03

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