Quel est l'avantage d'utiliser des getters et setters - qui ne sont que get et set - au lieu d'utiliser simplement des champs publics pour ces variables?
Si les getters et les setters font jamais plus que le simple get / set, je peux comprendre celui-ci très rapidement, mais je ne sais pas à 100% comment:
public String foo;
est pire que:
private String foo;
public void setFoo(String foo) { this.foo = foo; }
public String getFoo() { return foo; }
Alors que le premier prend beaucoup moins de code passe-partout.
Réponses:
Il existe en fait de nombreuses bonnes raisons pour envisager d'utiliser des accesseurs plutôt que d'exposer directement les champs d'une classe - au-delà de l'argument de l'encapsulation et de faciliter les changements futurs.
Voici quelques-unes des raisons que je connais:
la source
public
méthodes d'accesseur provoquent la duplication de code et exposent les informations. Les accesseurs publics ne sont pas nécessaires pour le marshaling (sérialisation). Dans certains langages (Java), lespublic
accesseurs get ne peuvent pas avoir le type de retour modifié sans casser les classes dépendantes. De plus, je pense qu'ils vont à l'encontre des principes OO. Voir aussi: stackoverflow.com/a/1462424/59087plane.turnTo(dir); plane.setSpeed(spd); plane.setTargetAltitude(alt); plane.getBreaks().release();
je veux direplane.takeOff(alt)
. Les champs de données internes qui doivent être modifiés pour mettre l'avion entakingOff
mode ne me préoccupent pas. Et quels autres objets (breaks
) la méthode notifie je ne veux pas savoir non plus.Parce que dans 2 semaines (mois, années) à partir de maintenant, lorsque vous réaliserez que votre setter doit faire plus que simplement définir la valeur, vous vous rendrez également compte que la propriété a été utilisée directement dans 238 autres classes :-)
la source
Un champ public n'est pas pire qu'une paire getter / setter qui ne fait rien d'autre que de renvoyer le champ et de l'affecter. Tout d'abord, il est clair que (dans la plupart des langues) il n'y a pas de différence fonctionnelle. Toute différence doit provenir d'autres facteurs, comme la maintenabilité ou la lisibilité.
Un avantage souvent mentionné des paires getter / setter ne l'est pas. Il y a cette affirmation selon laquelle vous pouvez modifier l'implémentation et vos clients n'ont pas besoin d'être recompilés. Soi-disant, les setters vous permettent d'ajouter des fonctionnalités comme la validation plus tard et vos clients n'ont même pas besoin de le savoir. Cependant, l'ajout de validation à un setter est une modification de ses conditions préalables, une violation du contrat précédent , qui était, tout simplement, "vous pouvez mettre n'importe quoi ici, et vous pouvez obtenir la même chose plus tard du getter".
Donc, maintenant que vous avez rompu le contrat, changer chaque fichier de la base de code est quelque chose que vous devriez faire, pas éviter. Si vous l'évitez, vous faites l'hypothèse que tout le code supposait que le contrat pour ces méthodes était différent.
Si cela ne devait pas être le contrat, alors l'interface permettait aux clients de mettre l'objet dans des états invalides. C'est exactement le contraire de l'encapsulation. Si ce champ ne pouvait pas vraiment être défini sur quoi que ce soit dès le début, pourquoi n'y avait-il pas la validation depuis le début?
Ce même argument s'applique à d'autres avantages supposés de ces paires getter / setter pass-through: si vous décidez ultérieurement de modifier la valeur définie, vous rompez le contrat. Si vous remplacez la fonctionnalité par défaut dans une classe dérivée, d'une manière au-delà de quelques modifications inoffensives (comme la journalisation ou tout autre comportement non observable), vous rompez le contrat de la classe de base. C'est une violation du principe de substituabilité de Liskov, qui est considéré comme l'un des principes de l'OO.
Si une classe a ces getters et setters stupides pour chaque domaine, alors c'est une classe qui n'a aucun invariant, aucun contrat . Est-ce vraiment une conception orientée objet? Si tout ce que la classe a est ces getters et setters, c'est juste un détenteur de données stupide, et les détenteurs de données stupides devraient ressembler à des détenteurs de données stupides:
L'ajout de paires getter / setter pass-through à une telle classe n'ajoute aucune valeur. Les autres classes devraient fournir des opérations significatives, pas seulement les opérations que les champs fournissent déjà. C'est ainsi que vous pouvez définir et maintenir des invariants utiles.
Il y a des raisons d'utiliser des getters et des setters, mais si ces raisons n'existent pas, faire des paires getter / setter au nom de faux dieux d'encapsulation n'est pas une bonne chose. Les raisons valables de faire des getters ou setters incluent les choses souvent mentionnées comme les changements potentiels que vous pouvez apporter plus tard, comme la validation ou différentes représentations internes. Ou peut-être que la valeur doit être lisible par les clients mais pas inscriptible (par exemple, lire la taille d'un dictionnaire), donc un simple getter est un bon choix. Mais ces raisons devraient être présentes lorsque vous faites le choix, et pas seulement comme une chose potentielle que vous voudrez peut-être plus tard. Ceci est une instance de YAGNI ( vous n'en aurez pas besoin ).
la source
private
champ. Si une classe n'a pas de setters, il est facile de la rendre immuable.Beaucoup de gens parlent des avantages des getters et setters mais je veux jouer l'avocat du diable. En ce moment, je débogue un très gros programme où les programmeurs ont décidé de tout faire getters et setters. Cela peut sembler agréable, mais c'est un cauchemar de rétro-ingénierie.
Imaginons que vous parcouriez des centaines de lignes de code et que vous tombiez sur ceci:
C'est un morceau de code magnifiquement simple jusqu'à ce que vous réalisiez que c'est un passeur. Maintenant, vous suivez ce setter et constatez qu'il définit également person.firstName, person.lastName, person.isHuman, person.hasReallyCommonFirstName et appelle person.update (), qui envoie une requête à la base de données, etc. Oh, c'est où votre fuite de mémoire se produisait.
Comprendre un morceau de code local à première vue est une propriété importante de bonne lisibilité que les getters et les setters ont tendance à casser. C'est pourquoi j'essaye de les éviter quand je le peux et de minimiser ce qu'ils font quand je les utilise.
la source
person.name = "Joe";
est appelé. Il n'y a pas de cruauté dans la manière de l'information, la mise en évidence de la syntaxe montre que c'est un champ et le refactoring est plus simple (pas besoin de refactoriser deux méthodes et un champ). Deuxièmement, tous ces cycles cérébraux gaspillés pensant «getIsValid ()» ou devrait-il être «isValid ()» etc. peuvent être oubliés. Je ne peux pas penser à une seule fois où j'ai été sauvé d'un bug par un getter / setter.Il y a plusieurs raisons. Mon préféré est quand vous devez changer le comportement ou régler ce que vous pouvez définir sur une variable. Par exemple, supposons que vous disposiez d'une méthode setSpeed (int speed). Mais vous voulez que vous ne puissiez définir qu'une vitesse maximale de 100. Vous feriez quelque chose comme:
Maintenant, que se passe-t-il si PARTOUT dans votre code vous utilisiez le domaine public et que vous vous rendez compte que vous avez besoin de l'exigence ci-dessus? Amusez-vous à traquer chaque utilisation du domaine public au lieu de simplement modifier votre setter.
Mes 2 cents :)
la source
while(speed < 200) { do_something(); accelerate(); }
)myCar.setSpeed(157);
et après quelques lignesspeed = myCar.getSpeed();
Et maintenant ... Je vous souhaite un bon débogage tout en essayant de comprendre pourquoispeed==100
quand cela devrait être157
Dans un monde purement orienté objet, les getters et setters sont un terrible anti-pattern . Lisez cet article: Getters / Setters. Mal. Période . En un mot, ils encouragent les programmeurs à penser les objets comme des structures de données, et ce type de pensée est purement procédural (comme dans COBOL ou C). Dans un langage orienté objet, il n'y a pas de structures de données, mais uniquement des objets qui exposent le comportement (pas les attributs / propriétés!)
Vous pouvez trouver plus d'informations à leur sujet dans la section 3.5 des objets élégants (mon livre sur la programmation orientée objet).
la source
new Dog()
n'est pas un chien. C'est un objet qui contient des informations sur un chien. Et pour cet usage, il est naturel de pouvoir corriger un poids mal enregistré.L'un des avantages des accesseurs et des mutateurs est que vous pouvez effectuer une validation.
Par exemple, s'il
foo
était public, je pourrais facilement le définirnull
et quelqu'un d'autre pourrait essayer d'appeler une méthode sur l'objet. Mais ce n'est plus là! Avec unesetFoo
méthode, je pouvais m'assurer que celafoo
n'était jamais réglénull
.Les accesseurs et les mutateurs permettent également l'encapsulation - si vous n'êtes pas censé voir la valeur une fois qu'elle est définie (peut-être qu'elle est définie dans le constructeur puis utilisée par des méthodes, mais qu'elle n'est jamais censée être modifiée), elle ne sera jamais vue par personne. Mais si vous pouvez autoriser d'autres classes à le voir ou à le modifier, vous pouvez fournir l'accesseur et / ou le mutateur approprié.
la source
Cela dépend de votre langue. Vous avez marqué ce "orienté objet" plutôt que "Java", donc je voudrais souligner que la réponse de ChssPly76 dépend du langage. En Python, par exemple, il n'y a aucune raison d'utiliser des getters et des setters. Si vous devez modifier le comportement, vous pouvez utiliser une propriété, qui enveloppe un getter et un setter autour de l'accès aux attributs de base. Quelque chose comme ça:
la source
obj.set_attr('foo')
) sont intrinsèquement supérieures aux signes égaux (obj.attr = 'foo'
). L'accès public est un accès public.obj.attr = 'foo'
ne définit que la variable sans que rien ne se passeobj.setAttr('foo')
"définit simplement la variable sans que rien d'autre ne se passe"? Si c'est une méthode publique, alors c'est une méthode publique. Si vous l'utilisez pour obtenir un effet secondaire et qu'il est public, vous feriez mieux de pouvoir compter sur tout ce qui fonctionne comme si seul cet effet secondaire prévu se produisait (avec tous les autres détails de mise en œuvre et autres effets secondaires, l'utilisation des ressources, etc.) , caché des préoccupations de l'utilisateur). Ce n'est absolument pas différent avec Python. La syntaxe de Python pour obtenir l'effet est simplement plus simple.Eh bien, je veux juste ajouter que même si parfois elles sont nécessaires pour l'encapsulation et la sécurité de vos variables / objets, si nous voulons coder un vrai programme orienté objet, alors nous devons ARRÊTER DE SURUTILISER LES ACCESSOIRES , car parfois nous dépendons beaucoup sur eux quand ce n'est pas vraiment nécessaire et cela fait presque la même chose que si nous mettons les variables publiques.
la source
Merci, cela a vraiment clarifié ma pensée. Voici maintenant (presque) 10 (presque) bonnes raisons de NE PAS utiliser les getters et setters:
Les trois derniers que je viens de quitter (N / A ou D / C) ...
la source
Je sais qu'il est un peu tard, mais je pense qu'il y a des gens qui s'intéressent à la performance.
J'ai fait un petit test de performance. J'ai écrit une classe "NumberHolder" qui, bien, contient un nombre entier. Vous pouvez lire cet entier en utilisant la méthode getter
anInstance.getNumber()
ou en accédant directement au numéro en utilisantanInstance.number
. Mon programme lit le nombre 1 000 000 000 fois, dans les deux sens. Ce processus est répété cinq fois et l'heure est imprimée. J'ai le résultat suivant:(Le temps 1 est le chemin direct, le temps 2 est le getter)
Vous voyez, le getter est (presque) toujours un peu plus rapide. J'ai ensuite essayé avec différents nombres de cycles. Au lieu d'un million, j'ai utilisé 10 millions et 0,1 million. Les resultats:
10 millions de cycles:
Avec 10 millions de cycles, les délais sont quasiment les mêmes. Voici 100 000 (0,1 million) cycles:
Toujours avec des quantités de cycles différentes, le getter est un peu plus rapide que la manière habituelle. J'espère que cela vous a aidé.
la source
N'utilisez pas de setters getters à moins que cela ne soit nécessaire pour votre livraison actuelle Ie Ne pensez pas trop à ce qui se passerait à l'avenir, si quelque chose à changer est une demande de changement dans la plupart des applications de production, des systèmes.
Pensez simple, facile, ajoutez de la complexité au besoin.
Je ne profiterais pas de l'ignorance des propriétaires d'entreprise possédant un savoir-faire technique approfondi simplement parce que je pense que c'est correct ou que j'aime l'approche.
J'ai un système massif écrit sans getters setters uniquement avec des modificateurs d'accès et quelques méthodes pour valider n exécuter la logique biz. Si vous en aviez absolument besoin. Utilisez n'importe quoi.
la source
Nous utilisons des getters et setters:
Les méthodes getter et setter sont des interfaces publiques pour accéder aux membres de classe privés.
Mantra d'encapsulation
Le mantra de l'encapsulation est de rendre les champs privés et les méthodes publiques.
Même si les méthodes getter et setter n'ajoutent pas de nouvelles fonctionnalités, nous pouvons changer d'avis revenir plus tard pour rendre cette méthode
Partout où une valeur peut être utilisée, une méthode qui renvoie cette valeur peut être ajoutée. Au lieu de:
utilisation
En termes simples
Supposons que nous ayons besoin d'en stocker les détails
Person
. CelaPerson
a les champsname
,age
etsex
. Pour ce faire, vous devez créer des méthodes pourname
,age
etsex
. Maintenant , si nous avons besoin de créer une autre personne, il devient nécessaire de créer les méthodes pourname
,age
,sex
encore une fois.Au lieu de cela, nous pouvons créer un bean
class(Person)
avec des méthodes getter et setter. Donc, demain, nous pouvons simplement créer des objets de ce Beanclass(Person class)
chaque fois que nous devons ajouter une nouvelle personne (voir la figure). Ainsi, nous réutilisons les champs et les méthodes de la classe bean, ce qui est bien mieux.la source
J'ai passé un bon moment à réfléchir à cela pour le cas Java, et je crois que les vraies raisons sont:
En d'autres termes, la seule façon de spécifier un champ dans une interface est de fournir une méthode pour écrire une nouvelle valeur et une méthode pour lire la valeur actuelle.
Ces méthodes sont le tristement célèbre getter et setter ....
la source
Il peut être utile pour le chargement paresseux. Supposons que l'objet en question soit stocké dans une base de données et que vous ne souhaitiez pas l'obtenir à moins d'en avoir besoin. Si l'objet est récupéré par un getter, alors l'objet interne peut être nul jusqu'à ce que quelqu'un le demande, alors vous pouvez aller le chercher lors du premier appel au getter.
J'ai eu une classe de page de base dans un projet qui m'a été remise qui chargeait des données à partir de quelques appels de service Web différents, mais les données de ces appels de service Web n'étaient pas toujours utilisées dans toutes les pages enfants. Les services Web, pour tous les avantages, ouvrent la voie à de nouvelles définitions de «lent», de sorte que vous ne voulez pas passer un appel de service Web si vous n'êtes pas obligé.
Je suis passé des champs publics aux getters, et maintenant les getters vérifient le cache, et s'il n'est pas là, appelez le service Web. Donc, avec un peu d'emballage, beaucoup d'appels de service Web ont été empêchés.
Ainsi, le getter me sauve d'essayer de comprendre, sur chaque page enfant, ce dont j'ai besoin. Si j'en ai besoin, j'appelle le getter, et il va le trouver pour moi si je ne l'ai pas déjà.
la source
Un aspect que j'ai manqué dans les réponses jusqu'à présent, la spécification d'accès:
la source
EDIT: J'ai répondu à cette question car il y a beaucoup de gens qui apprennent la programmation qui le demandent, et la plupart des réponses sont très compétentes techniquement, mais elles ne sont pas aussi faciles à comprendre si vous êtes un débutant. Nous étions tous des débutants, alors j'ai pensé essayer une réponse plus amicale aux débutants.
Les deux principaux sont le polymorphisme et la validation. Même si ce n'est qu'une stupide structure de données.
Disons que nous avons cette classe simple:
Une classe très simple qui contient la quantité de liquide qu'il contient et sa capacité (en millilitres).
Que se passe-t-il quand je le fais:
Eh bien, vous ne vous attendriez pas à ce que cela fonctionne, non? Vous voulez qu'il y ait une sorte de contrôle de santé mentale. Et pire, que se passe-t-il si je n'ai jamais spécifié la capacité maximale? Oh mon cher, nous avons un problème.
Mais il y a aussi un autre problème. Et si les bouteilles n'étaient qu'un type de récipient? Et si nous avions plusieurs conteneurs, tous avec des capacités et des quantités de liquide remplies? Si nous pouvions simplement créer une interface, nous pourrions laisser le reste de notre programme accepter cette interface, et les bouteilles, les jerrycans et toutes sortes de choses fonctionneraient de manière interchangeable. Ce ne serait pas mieux? Comme les interfaces demandent des méthodes, c'est aussi une bonne chose.
Nous finirions avec quelque chose comme:
Génial! Et maintenant, nous changeons simplement la bouteille en ceci:
Je laisse la définition de la BottleOverflowException comme un exercice au lecteur.
Maintenant, remarquez à quel point c'est plus robuste. Nous pouvons traiter tout type de conteneur dans notre code maintenant en acceptant LiquidContainer au lieu de Bottle. Et la façon dont ces bouteilles traitent ce genre de choses peut différer. Vous pouvez avoir des bouteilles qui écrivent leur état sur le disque lorsqu'il change, ou des bouteilles qui enregistrent sur des bases de données SQL ou GNU sait quoi d'autre.
Et tout cela peut avoir différentes façons de gérer diverses whoopsies. La bouteille vérifie simplement et si elle déborde, elle lance une RuntimeException. Mais ce n'est peut-être pas la bonne chose à faire. (Il y a une discussion utile à avoir sur le traitement des erreurs, mais je le maintiens très simple ici exprès. Les personnes dans les commentaires vont probablement souligner les défauts de cette approche simpliste.;))
Et oui, il semble que nous passions d'une idée très simple à des réponses bien meilleures rapidement.
Veuillez également noter que vous ne pouvez pas modifier la capacité d'une bouteille. Il est maintenant gravé dans la pierre. Vous pouvez le faire avec un int en le déclarant final. Mais s'il s'agissait d'une liste, vous pouvez la vider, y ajouter de nouvelles choses, etc. Vous ne pouvez pas limiter l'accès à toucher les entrailles.
Il y a aussi la troisième chose que tout le monde n'a pas abordée: les getters et les setters utilisent des appels de méthode. Cela signifie qu'ils ressemblent à des méthodes normales partout ailleurs. Au lieu d'avoir une syntaxe spécifique bizarre pour les DTO et autres choses, vous avez la même chose partout.
la source
Dans les langages qui ne prennent pas en charge les «propriétés» (C ++, Java) ou qui nécessitent une recompilation des clients lors de la modification des champs en propriétés (C #), l'utilisation des méthodes get / set est plus facile à modifier. Par exemple, l'ajout d'une logique de validation à une méthode setFoo ne nécessitera pas de modifier l'interface publique d'une classe.
Dans les langages qui prennent en charge les propriétés "réelles" (Python, Ruby, peut-être Smalltalk?), Il est inutile d'obtenir des méthodes / set.
la source
L'un des principes de base de la conception OO: l' encapsulation!
Cela vous offre de nombreux avantages, dont l'un est que vous pouvez modifier la mise en œuvre du getter / setter dans les coulisses, mais tout consommateur de cette valeur continuera de fonctionner tant que le type de données reste le même.
la source
Vous devez utiliser des getters et setters lorsque:
Il s'agit donc très rarement d'une question d'ordre général; c'est une question spécifique à la langue, avec des réponses différentes pour différentes langues (et différents cas d'utilisation).
Du point de vue de la théorie OO, les getters et setters sont inutiles. L'interface de votre classe est ce qu'elle fait, pas quel est son état. (Sinon, vous avez écrit la mauvaise classe.) Dans des cas très simples, où ce que fait une classe est simplement, par exemple, représenter un point en coordonnées rectangulaires, * les attributs font partie de l'interface; les getters et les setters ne font qu'obscurcir cela. Mais dans tout sauf des cas très simples, ni les attributs ni les getters et setters ne font partie de l'interface.
Autrement dit: si vous pensez que les consommateurs de votre classe ne devraient même pas savoir que vous avez un
spam
attribut, et encore moins pouvoir le changer bon gré mal gré, alors leur donner uneset_spam
méthode est la dernière chose que vous voulez faire.* Même pour cette classe simple, vous ne voudrez pas nécessairement autoriser la définition des valeurs
x
ety
. Si cela est vraiment une classe, il ne devrait pas avoir des méthodes telles quetranslate
,rotate
etc.? Si ce n'est qu'une classe parce que votre langage n'a pas d'enregistrements / structures / tuples nommés, alors ce n'est pas vraiment une question d'OO…Mais personne ne fait jamais de conception OO générale. Ils font la conception et l'implémentation dans un langage spécifique. Et dans certaines langues, les getters et setters sont loin d'être inutiles.
Si votre langue n'a pas de propriétés, alors la seule façon de représenter quelque chose qui est conceptuellement un attribut, mais qui est en fait calculé, ou validé, etc., est par le biais de getters et setters.
Même si votre langue a des propriétés, il peut y avoir des cas où elles sont insuffisantes ou inappropriées. Par exemple, si vous souhaitez autoriser les sous-classes à contrôler la sémantique d'un attribut, dans les langues sans accès dynamique, une sous-classe ne peut pas substituer une propriété calculée à un attribut.
Quant à la "que se passe-t-il si je veux changer ma mise en œuvre plus tard?" question (qui est répétée plusieurs fois dans une formulation différente à la fois dans la question du PO et dans la réponse acceptée): s'il s'agit vraiment d'un changement d'implémentation pur et que vous avez commencé avec un attribut, vous pouvez le changer en propriété sans affecter l'interface. À moins, bien sûr, que votre langue ne le prenne pas en charge. Donc, c'est vraiment encore le même cas.
De plus, il est important de suivre les idiomes du langage (ou du framework) que vous utilisez. Si vous écrivez un beau code de style Ruby en C #, tout développeur C # expérimenté autre que vous aura du mal à le lire, et c'est mauvais. Certaines langues ont des cultures plus fortes autour de leurs conventions que d'autres. - et ce n'est peut-être pas une coïncidence si Java et Python, qui sont aux extrémités opposées du spectre des getters idiomatiques, ont deux des cultures les plus fortes.
Au-delà des lecteurs humains, il y aura des bibliothèques et des outils qui s'attendent à ce que vous suiviez les conventions et rendiez votre vie plus difficile si vous ne le faites pas. Accrocher les widgets d'Interface Builder à autre chose que les propriétés ObjC, ou utiliser certaines bibliothèques de simulation Java sans getters, vous rend la vie plus difficile. Si les outils sont importants pour vous, ne les combattez pas.
la source
Du point de vue de la conception orientée objet, les deux alternatives peuvent être préjudiciables à la maintenance du code en affaiblissant l'encapsulation des classes. Pour une discussion, vous pouvez consulter cet excellent article: http://typicalprogrammer.com/?p=23
la source
Les méthodes getter et setter sont des méthodes d'accesseur, ce qui signifie qu'elles sont généralement une interface publique pour changer les membres d'une classe privée. Vous utilisez des méthodes getter et setter pour définir une propriété. Vous accédez aux méthodes getter et setter en tant que propriétés en dehors de la classe, même si vous les définissez dans la classe en tant que méthodes. Ces propriétés en dehors de la classe peuvent avoir un nom différent de celui de la classe.
L'utilisation des méthodes getter et setter présente certains avantages, tels que la possibilité de vous permettre de créer des membres avec des fonctionnalités sophistiquées auxquelles vous pouvez accéder comme des propriétés. Ils vous permettent également de créer des propriétés en lecture seule et en écriture seule.
Même si les méthodes getter et setter sont utiles, vous devez faire attention à ne pas en abuser car, entre autres, elles peuvent rendre la maintenance du code plus difficile dans certaines situations. En outre, ils donnent accès à votre implémentation de classe, comme les membres publics. La pratique de la POO décourage l'accès direct aux propriétés d'une classe.
Lorsque vous écrivez des classes, vous êtes toujours encouragé à rendre le plus grand nombre possible de variables d'instance privées et à ajouter des méthodes getter et setter en conséquence. En effet, il peut arriver à plusieurs reprises que vous ne souhaitiez pas permettre aux utilisateurs de modifier certaines variables au sein de vos classes. Par exemple, si vous disposez d'une méthode statique privée qui suit le nombre d'instances créées pour une classe spécifique, vous ne voulez pas qu'un utilisateur modifie ce compteur à l'aide de code. Seule l'instruction constructeur doit incrémenter cette variable chaque fois qu'elle est appelée. Dans cette situation, vous pouvez créer une variable d'instance privée et autoriser une méthode getter uniquement pour la variable compteur, ce qui signifie que les utilisateurs ne peuvent récupérer la valeur actuelle qu'en utilisant la méthode getter et qu'ils ne pourront pas définir de nouvelles valeurs en utilisant la méthode setter.
la source
Le code évolue .
private
est idéal lorsque vous avez besoin d'une protection des membres de données . Finalement, toutes les classes devraient être en quelque sorte des "mini-programmes" qui ont une interface bien définie que vous ne pouvez pas simplement visser avec les internes de .Cela dit, le développement logiciel ne consiste pas à installer cette version finale de la classe comme si vous appuyiez sur une statue en fonte du premier coup. Pendant que vous travaillez avec, le code ressemble plus à de l'argile. Il évolue au fur et à mesure que vous le développez et en apprenez davantage sur le domaine de problème que vous résolvez. Au cours du développement, les classes peuvent interagir les unes avec les autres comme elles le devraient (dépendance que vous prévoyez de prendre en compte), fusionner ou se séparer. Je pense donc que le débat se résume à des gens qui ne veulent pas écrire religieusement
Vous avez donc:
Au lieu de
Non seulement il est
getVar()
visuellement bruyant, mais il donne cette illusion quigettingVar()
est en quelque sorte un processus plus complexe qu'il ne l'est réellement. La façon dont vous (en tant qu'écrivain de classe) considérez le caractère sacré devar
est particulièrement déroutante pour un utilisateur de votre classe s'il a un passeur - alors il semble que vous installez ces portes pour "protéger" quelque chose que vous insistez est précieux, (le caractère sacré devar
) mais pourtant, même vous concédez quevar
la protection ne vaut pas grand-chose par la capacité de quiconque à entrer etset
var
à la valeur qu'il veut, sans même que vous jetiez un œil à ce qu'il fait.Je programme donc comme suit (en supposant une approche de type "agile" - c'est-à-dire quand j'écris du code ne sachant pas exactement ce qu'il va faire / je n'ai pas le temps ou l'expérience pour planifier un ensemble d'interface de style cascade sophistiqué):
1) Commencez avec tous les membres publics pour les objets de base avec des données et un comportement. C'est pourquoi dans tout mon code "exemple" C ++, vous remarquerez que j'utilise à la
struct
place declass
partout.2) Lorsque le comportement interne d'un objet pour un membre de données devient suffisamment complexe (par exemple, il aime conserver un interne
std::list
dans un certain ordre), des fonctions de type accesseur sont écrites. Parce que je programme par moi-même, je ne mets pas toujours le membreprivate
tout de suite, mais quelque part dans l'évolution de la classe, le membre sera "promu" à l'unprotected
ou à l'autreprivate
.3) Les classes qui sont entièrement étoffées et ont des règles strictes sur leurs internes (c'est-à-dire qu'elles savent exactement ce qu'elles font, et vous ne devez pas "baiser" (terme technique) avec ses internes) reçoivent la
class
désignation, membres privés par défaut, et seuls quelques membres sélectionnés sont autorisés à l'êtrepublic
.Je trouve que cette approche me permet d'éviter de rester assis là et d'écrire religieusement des getter / setters lorsque beaucoup de membres de données sont migrés, déplacés, etc. pendant les premières étapes de l'évolution d'une classe.
la source
Il y a une bonne raison d'envisager l'utilisation d'accesseurs car il n'y a pas d'héritage de propriété. Voir l'exemple suivant:
Production:
la source
Les getters et setters sont utilisés pour implémenter deux des aspects fondamentaux de la programmation orientée objet qui sont:
Supposons que nous ayons une classe Employé:
Ici, les détails d'implémentation du nom complet sont cachés à l'utilisateur et ne sont pas accessibles directement à l'utilisateur, contrairement à un attribut public.
la source
Une autre utilisation (dans les langages qui prennent en charge les propriétés) est que les setters et les getters peuvent impliquer qu'une opération n'est pas triviale. En règle générale, vous voulez éviter de faire quoi que ce soit de coûteux en calcul dans une propriété.
la source
execute
oubuild
méthode.Un avantage relativement moderne des getters / setters est qu'il facilite la navigation dans les éditeurs de code balisés (indexés). Par exemple, si vous voulez voir qui définit un membre, vous pouvez ouvrir la hiérarchie des appels du passeur.
En revanche, si le membre est public, les outils ne permettent pas de filtrer l'accès en lecture / écriture au membre. Vous devez donc vous frayer un chemin dans toutes les utilisations du membre.
la source
Dans un langage orienté objet, les méthodes et leurs modificateurs d'accès déclarent l'interface de cet objet. Entre le constructeur et les méthodes d'accesseur et de mutateur, il est possible pour le développeur de contrôler l'accès à l'état interne d'un objet. Si les variables sont simplement déclarées publiques, il n'y a aucun moyen de réglementer cet accès. Et lorsque nous utilisons des setters, nous pouvons restreindre l'utilisateur pour l'entrée dont nous avons besoin. Signifier que le flux pour cette variable très passera par un canal approprié et le canal est prédéfini par nous. Il est donc plus sûr d'utiliser des setters.
la source
De plus, c'est pour "pérenniser" votre classe. En particulier, le passage d'un champ à une propriété est une rupture ABI, donc si vous décidez plus tard que vous avez besoin de plus de logique que simplement "définir / obtenir le champ", alors vous devez rompre ABI, ce qui crée bien sûr des problèmes pour quoi que ce soit sinon déjà compilé contre votre classe.
la source
Je voudrais juste lancer l'idée d'annotation: @getter et @setter. Avec @getter, vous devriez pouvoir obj = class.field mais pas class.field = obj. Avec @setter, vice versa. Avec @getter et @setter, vous devriez pouvoir faire les deux. Cela préserverait l'encapsulation et réduirait le temps en n'appelant pas de méthodes triviales à l'exécution.
la source