Partage
  • Partager sur Facebook
  • Partager sur Twitter

Pourquoi utiliser des Getters et Setters ?

Sujet résolu
    15 février 2018 à 19:23:55

    Hello tout le monde,

    Je débute en Java et j'ai peut-être raté une subtilité mais :

    je ne saisis pas très bien pourquoi mettre une variable d'instance en private si c'est pour la rendre quand même accessible ET modifiable en dehors de sa classe avec des getters et setters ... ? 

    Quelle est la différence ?

    • Partager sur Facebook
    • Partager sur Twitter
      15 février 2018 à 19:34:51

      Bonjour.

      Parce que dans la théorie de la POO il y a l'encapsulation : la modification de l'état d'un objet est fait uniquement par les méthodes qu'il expose.
      L'erreurs courantes est de réfléchir attribut avant de réfléchir fonctionnalité, imposant ainsi de créer systématiquement les accesseurs (getter + setter) associés.

      Exception à cette règle : les POJO (Plain Old Java Object), tels que les DTO (Data Transfert Object) ou @Entity (mapping des tables d'une base de données en JPA), qui ne sont là que pour stocker des données sans intelligence.

      • Partager sur Facebook
      • Partager sur Twitter
      Angular 2 est l'avenir, jQuery c'est de la merde !!! - Java 8 c'est l'an 2016+ (programmez en 1 ligne)
        15 février 2018 à 19:51:49

        Merci pour ta réponse. 

        Je suis pas sûr que ça soit clair :
        Si on encapsule c'est bien pour des raisons de sécurité ? Pour éviter qu'on puisse accéder à une variable de l'extérieur. J'ai bien compris ?

        En quoi passer par les getters et setters protège la classe, puisque justement ça rend les variables accessibles et modifiables ?

        Edit:
        OK, non je crois que j'ai compris en fait :
        La sécurité de l'encapsulation ne consiste pas à empêcher l'accès à une variable, mais d'en "contrôler" l'accès pour qu'on ne puisse pas faire TOUT ce qu'on veut avec de l'extérieur de la classe.

        -
        Edité par leneelph 15 février 2018 à 20:01:31

        • Partager sur Facebook
        • Partager sur Twitter
          15 février 2018 à 20:03:20

          On peut effectuer des contrôles dans un "setter", par exemple vérifier si l'attribut est déjà initialisé, ou vérifier que le paramètre n'est pas nul.
          De même que l'on peut effectuer des opérations dans un "getter", par exemple retourner la copie d'un liste plutôt que la liste directement.

          Mais de manière générale les setters doivent être inexistant, et les getters limités.
          Si c'est la 1ère chose qui est implémentée lorsque l'on crée une classe, alors c'est un problème de conception.

          • Partager sur Facebook
          • Partager sur Twitter
          Angular 2 est l'avenir, jQuery c'est de la merde !!! - Java 8 c'est l'an 2016+ (programmez en 1 ligne)
            16 février 2018 à 8:19:46

            Bonjour,

            Pour compléter ce qu'a dit Pinguet, j'ajouterais qu'il ne faut pas voir les getters et setters comme un moyen d'accéder à des attributs mais bien comme des fonctionnalités à part entière (indépendantes des attributs).

            Ca permet aussi de changer l'implémentation de tes classes sans affecter le code existant qui les utilise. Tant que tes méthodes gardent la même signature, tu peux modifier tes attributs à ta guise pour rendre ton code plus propre et/ou plus efficace.

            • Partager sur Facebook
            • Partager sur Twitter
              1 mars 2018 à 22:40:34

              pour tous ceux qui passeraient par là et qui se posent la même question : si vous ne saisissez pas du premier coup c'est que la notion d'encapsulation qui est le premier principe de la POO reste encore trop floue pour vous.

              n'hésitez pas à prendre le temps de clarifier ça avant de passer à autre chose, lire, regarder des cas pratiques (avec/sans encapsulation).

              Si vous comprenez l'encapsulation, l'utilisation des getters et setters devient évidente en fait.

              merci pour vos réponses, j'ai eu comme un déclic ! lol

              • Partager sur Facebook
              • Partager sur Twitter
                2 mars 2018 à 17:15:53

                leneelph a écrit:

                pour tous ceux qui passeraient par là et qui se posent la même question : si vous ne saisissez pas du premier coup c'est que la notion d'encapsulation qui est le premier principe de la POO reste encore trop floue pour vous.

                n'hésitez pas à prendre le temps de clarifier ça avant de passer à autre chose, lire, regarder des cas pratiques (avec/sans encapsulation).

                Si vous comprenez l'encapsulation, l'utilisation des getters et setters devient évidente en fait.


                Hé hé. Pour moi, le premier principe, c'est l'abstraction :)

                Les réponses de Pinguet62 contiennent plein de sagesse, il ne rentre pas dans les détails, mais ce qu'il explique est à relire tranquillement et plus d'une fois :)

                Le premier truc important en POO: "quel est le service de ton objet va remplir pour toi?". Si tu commences à te dire: "mais comment est-ce qu'il est foutu?", il y a de fortes chances que tu te poses les mauvaises questions. C'est la chose la plus difficile au début.

                De là, à partir du moment où tu penses à ce que l'objet peut faire, tu ne te poseras plus la question de s'il faut exposer les données. Par défaut, c'est non. Peut-être que le service sera d'exposer une donnée. Alors là, OK. Expose. Mais, on est alors loin des fondamentaux OO.

                Après un setter n'est pas un renforcement d'encapsulation. Si l'objet a un invariant et que le setter réalise un contrôle, cela veut dire que le setter a un nom qui ment. Il ne "sette" pas, il "sette sous certaines conditions". De plus, on n'encapsule pas pour cacher, mais pour assurer ces fameux invariants. Si on commence à permettre de modifier des données internes de façon décorrélées, on peut vite avoir des surprises.
                Imagine une classe de nombres rationnels dont l'invariant est "PGCD(num, den) == 1, et den > 0". Qu'à un instant donné tu as une instance qui vaille 1/2 et que tu veuilles avoir à la place 4/3. Si tu enchaînes les opérations r.setNum(4), r.setDen(3), tu as alors toutes les chances de te retrouver avec 2/3 au lieu de 4/3 si tes setters prennent en charge la garantie des invariants. Ouch! Pourtant ils encapsulent bien...

                Bref, plein de littérature si tu cherches "Why setters are evil?".

                -
                Edité par lmghs 2 mars 2018 à 17:16:15

                • Partager sur Facebook
                • Partager sur Twitter
                C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                  3 mars 2018 à 22:04:11

                  wow, lmghs tout ça a l'air bien plus profond que les réponses light qu'on me donne en cours. 

                  Je vais prendre le temps qu'il faudra pour digérer tout ça, merci beaucoup.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    4 mars 2018 à 11:24:03

                    En fait ce n'est pas bien difficile. L'erreur est de concevoir des classes en pensant en premier à ce qu'on va mettre comme champs. Tout faux. La La bonne question, c'est de se demander ce qu'on va faire avec l'objet, comment on va l'employer.

                    La mauvaise approche est souvent confortée par les mauvais exemples qui sont donnés dans les cours. Si on reprend l'exemple des rationnels, il faut pousser plus loin la réflexion que de se dire "il y a un numérateur et un dénominateur". Et il ne suffit pas de dire que getNum et getDen retournent les éléments du rationnel simplifié.

                    Il faut déjà se poser la question de ce qu'on fait. La classe Rational est elle là pour représenter un nombre, ou une variable contenant un nombre ? Dans le premier cas, c'est un "immutable", pas de setter pour le numérateur et le dénominateur.

                    Dans le second, il faut se poser une autre question : si on a construit un rationnel à partir d'entiers "non normalisés"  (par exemple 3/6), qu'est ce que ça veut dire de changer le numérateur en 2 ? Ca devient 2/6, ou 2/1 ?

                    • Partager sur Facebook
                    • Partager sur Twitter

                    Pourquoi utiliser des Getters et Setters ?

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown