Pourquoi utiliser des getters et setters/accesseurs?
Quel est l'avantage d'utiliser les accesseurs et mutateurs - que seuls les get et set - au lieu de simplement en utilisant les champs de ces variables?
Si les getters et les setters sont de plus en plus que la simple get/set, je peux comprendre ça très vite, mais je ne suis pas 100% clair sur la façon dont:
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 réutilisable.
- J: Doublon avec beaucoup d'autres questions: stackoverflow.com/search?q=getters+setters
- Bien sûr, les deux sont aussi mauvais l'un que lorsque l'objet n'a pas besoin d'une propriété afin d'être changé. Je préfère tout faire en privé, et ensuite ajouter des accesseurs si utile, et en établissant, si nécessaire.
- Google "accesseurs sont mal"
- "Accesseurs sont mal" si vous arrive d'être de l'écriture de code fonctionnel ou des objets immuables. Si vous arrive d'être écrit stateful mutable objets, puis ils sont assez à l'essentiel.
- Dire, ne demandez pas. pragprog.com/articles/tell-dont-ask
- À l'exception de 6 et 8, oserais-je dire qu'aucun de ces points sont appliquées dans 99% des cas. Encore, je voudrais java utiliser
String s = employee.name()
etemployee.name("oscar")
au lieu de getName() setName() - Reyes, oui, je serais d'accord que 6 & 8 sont les deux plus courants à partir de mon expérience. Cela dit, je préfère encore ne pas utiliser le C#ish syntaxe; mon vieux cerveau est confus.
- Eh bien, je suis étonné que personne ne parle de la synchronisation des données. Supposons que vous utilisez
public String foo;
ses pas thread-safe! Au lieu de cela, vous pouvez définirget
terset
ters avec des techniques de synchronisation pour éviter l'infidélité[je veux dire un autre thread gâcher la foo]. J'ai senti qu'il vaut la peine de mentionner. - Plus souvent que jamais, la synchronisation de l'unique accès à un objet est inefficace, ou même sujette à des problèmes de synchronisation (quand vous avez besoin de modifier plusieurs propriétés d'un objet à la fois). IME, vous avez souvent besoin d'envelopper l'ensemble des opérations qui n'plusieurs accès à un objet. Qui ne peut être accompli que par la synchronisation sur le côté des utilisateurs d'un type.
- Ne pas compiler vos parties préférées de toutes les réponses dans la question elle-même. C'est un Q&Un site, pas un forum.
- que devrais-je lire pour comprendre la programmation orientée objet en premier lieu?
- Il y a aussi la très importante question de partage de code avec d'autres, si vous traitez les champs d'objet comme des parties de l'extérieur de l'interface pour d'autres personnes à utiliser ensuite de changer le domaine d'une fonction peut être impossible sans casser des changements dans d'autres peuples code.
- Merci pour le lien, je suis en train de travailler sur la compréhension de la programmation orientée objet est censé être, mais il s'avère difficile avec la quantité de désinformation qui circulent. P. S. j'ai aussi trouver wikipédia pour être l'une des meilleures sources dans de nombreux domaines scientifiques.
- il est tout au sujet de ne pas avoir à savoir qui de 500 fonctions est en fait de modifier une valeur. Vous apportez une valeur ou un ensemble de valeurs de quelque chose de la responsabilité, plutôt que quelque chose qui doit être placé sur un param/retour en dents de scie. Éviter de vanille getters/setters et les propriétés publiques et vous aurez souvent trouver vous-même avoir à vous arrêter et de réfléchir à comment le modèle de votre application dans une manière qui est généralement plus facile à lire, modifier, réutiliser, grandes pièces de, de débogage, et de leur faire confiance sans tester la bejeezus hors de lui. Java et C# overfeatured de la programmation orientée objet, puis l'a abandonné, de l'OMI.
- Un autre article tente de lignes directrices sur où et quand utiliser les accesseurs et mutateurs: Public ou Privé, Membre des Variables? Le principe de YAGNI nous guide à ne pas ajouter des constructions jusqu'à ce que nous savons vraiment, nous allons avoir besoin d'eux.
- Points 2, 3 (?), 4, 5 et 8: provisoire oui. Les autres, clairement non. Pourquoi importe-t-il si vous avez utilisé Python, C#, Ruby, Objective-C ou un esolang si votre code est simple, élégant et facilement maintenable/extensible?
- 666 upvotes ne semble pas être une coïncidence
- "Les gens peuvent facilement vous dire de ne pas utiliser Python." devrait en fait être N ° 1!
- Pourriez-vous illustrer comment c'est une bonne chose?
- Avez-vous l'esprit en expliquant le numéro 10?
- J'étais juste une blague, parce que l'auteur a clairement n'était pas grave lors de l'ajout à la liste.
- 11. Ce sont des endroits utiles pour définir des points d'arrêt lors du débogage d'état (extrait/modifié à partir de divers endroits.
- Une récente question m'a rappelé une autre raison pour les méthodes: la capacité de déclencher une changement de propriété d'.
Vous devez vous connecter pour publier un commentaire.
Il y a en fait de nombreuses bonnes raisons 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 faire les futurs changements plus facile.
Ici sont quelques-unes des raisons pour lesquelles je suis conscient de:
public
méthodes d'accès à l'entraîner la duplication de code, et d'exposer des informations. Public accesseurs ne sont pas nécessaires pour mobiliser (sérialisation). Dans certains langages (Java),public
accesseurs get ne peut pas avoir le type de retour changé sans casser des classes dépendantes. En outre, je crois qu'elles vont à l'encontre OO principes. Voir aussi: stackoverflow.com/a/1462424/59087plane.turnTo(dir); plane.setSpeed(spd); plane.setTargetAltitude(alt); plane.getBreaks().release();
je veux direplane.takeOff(alt)
. Ce que l'intérieur de champs de données doivent être modifiées afin de mettre l'avion dans latakingOff
mode est aucun de mes préoccupations. Et quels sont les autres objets (breaks
) la méthode avertit que je ne veux pas le savoir non plus.Insulating your public interface from change - allowing the public interface to remain constant while the implementation changes without affecting existing consumers.
- Bon point. De cette façon, vous avez moins de travail plus tard. De sorte que vous ne changer l'intérieur le contenu d'une classe plus tard.Parce que 2 semaines (mois, années) à partir de maintenant, lorsque vous vous rendez compte que votre poseur doit faire plus qu'il suffit de régler la valeur, vous pourrez aussi réaliser que la propriété a été utilisée directement dans 238 autres classes 🙂
ed
, et parfois, c'est l'outil pour le travail. Logiciel d'écriture, cependant, n'est pas un de ces moments.first_name
et, évidemment, vous voulez juste obtenir que le champ mot à mot, un point. Et vous devez utiliser un getter. Pour les p'têt ben que dans le futur, vous serez complètement changer la mise en œuvre de votre classe, tels que la classe asyncroneously récupère ce à partir d'un serveur ou n'importe quoi d'autre.person
t-il pour stocker les nom et prénom, puis c'est rien, mais un (glorifié)struct
et, par conséquent, pas de la POO, mais la Programmation Structurée. (Si les setters et getters le gain de rien dans ce scénario plus clairement l'accès aux données est douteuse au mieux: A) de Quelle autre manière, mais dans une chaîne que vous représentez une les noms de personne? Et je parle des scénarios pratiques ici, pas de la théorie, parce que B) en 20 ans de pratique je n'ai jamais couru dans une telle situation.)person
peut se marier à changer son nom (p1.marry(p2, p2.lastname())
), ou de divorce, ou de tout ce qui pousse les gens à changer leurs noms dans les différentes cultures. Il n'y a pas besoin de prendre directement au nom d'une personne. Veuillez lire les deux articles liés à partir de ce commentaire.Un champ public n'est pas pire qu'un getter/setter paire qui ne fait que retourner le terrain et en lui attribuant. 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 être dans d'autres facteurs, comme la maintenabilité ou la lisibilité.
Souvent mentionné avantage de getter/setter paires, n'est-ce pas. Il y a cette demande, vous pouvez changer la mise en œuvre et vos clients n'ont pas à être recompilé. Soi-disant, les poseurs 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 d'une validation à un setter est un changement de ses conditions préalables, une violation du contrat précédent, qui a été, tout simplement, "vous pouvez mettre n'importe quoi ici, et vous pouvez obtenir la même chose plus tard à partir de la lecture".
Donc, maintenant que vous avez cassé le contrat, la modification de chaque fichier dans la base de code est quelque chose que vous devriez vous voulez à faire, ne pas éviter. Si vous éviter cela, vous êtes en faisant l'hypothèse que tout le code suppose que le contrat de ces méthodes est différent.
Si cela ne devrait pas avoir été le contrat, l'interface a été permettant aux clients de mettre l'objet dans des états non valides. C'est l'exact opposé de l'encapsulation Si ce champ n'a pas vraiment pu être réglé à n'importe quoi depuis le début, pourquoi n'était-ce pas la validation depuis le début?
Ce même argument s'applique à d'autres avantages supposés de ces pass-through getter/setter paires: si plus tard vous décidez de changer la valeur en cours de jeu, vous êtes de rompre le contrat. Si vous remplacez la valeur par défaut de la fonctionnalité dans une classe dérivée, de façon au-delà de quelques modifications inoffensifs (comme l'exploitation forestière ou à d'autres comportements observables), vous êtes de rompre le contrat de la classe de base. C'est une violation de la Liskov Substituabilité Principe, qui est considéré comme l'un des principes de OO.
Si une classe a muettes getters et setters pour chaque champ, il est une classe qui n'a pas d'invariants que ce soit, pas de contrat. Est-ce vraiment une conception orientée objet? Si l'ensemble de la classe a, c'est ceux des getters et setters, c'est juste un idiot de données de titulaire, et de la muette que les détenteurs de données devrait ressembler muette que les détenteurs de données:
L'ajout de passage-à travers les getter/setter paires à une telle classe n'ajoute pas de valeur. D'autres classes devraient fournir des activités, et pas seulement les opérations que les champs fournissent déjà. C'est la façon dont vous pouvez définir et maintenir utile invariants.
Il y a des raisons d'utiliser les accesseurs et mutateurs, mais si ces raisons n'existent pas, faire des getter/setter paires dans le nom de faux encapsulation des dieux n'est pas une bonne chose. Des raisons valables de le faire getters ou setters comprennent les choses est souvent mentionné comme le potentiel de changements que vous pouvez faire plus tard, comme la validation ou différentes représentations internes. Ou peut-être la valeur doit être lisible par les clients, mais pas en écriture (par exemple, la lecture de la taille d'un dictionnaire), de sorte qu'un simple getter est un bon choix. Mais ces raisons devraient être là quand vous faites le choix, et pas seulement comme un potentiel de chose que vous souhaitez peut-être plus tard. C'est une instance de YAGNI (Vous Ain't Gonna Besoin).
private
champ. Si une classe n'a pas de setters, il est facile de rendre immuable....this claim that you can change the implementation and your clients don't have to be recompiled.
n'est faux si vous modifiez le contrat. Vous pouvez modifier tous les éléments internes d'un type sans modification de son contrat et de sa capacité à le faire est la raison pour laquelle l'encapsulation est une chose. Vous avez raison en indiquant que la modification du contrat sans passer en revue le code qui dépend de ce qui est mal, mais ce n'est pas pourquoi les accesseurs/propriétés existent de toute façon, c'est plutôt une mauvaise utilisation d'une convention qui est presque toujours recommandé, à moins que le type est la garantie d'avoir le même fonctionnement interne/mise en œuvre.Beaucoup de gens parler des avantages de getters et setters, mais je veux jouer l'avocat du diable. Droit maintenant, je suis le débogage d'un programme très important où les programmeurs ont décidé de faire tout ce que les accesseurs et mutateurs. Cela peut sembler agréable, mais c'est un reverse-engineering cauchemar.
Dire que vous êtes à la recherche à travers des centaines de lignes de code et vous tombez sur ce:
C'est une belle simplement morceau de code jusqu'à ce que vous vous rendez compte son un setter. Maintenant, vous suivez que compositeur et trouver qu'il définit personne.prenom, personne.nom, personne.isHuman, personne.hasReallyCommonFirstName, et les appels de personne.mise à jour(), qui envoie une requête à la base de données, etc. Oh, c'est là que votre fuite de mémoire qui se passait.
La compréhension d'un local morceau de code à première vue, est une propriété importante de la bonne lisibilité des getters et setters ont tendance à se briser. C'est pourquoi j'essaie de les éviter quand je le peux, et de réduire au minimum ce qu'ils font quand je les utilise.
person.name = "Joe";
est appelé. Il n'y a aucun trucs dans la voie de l'information, 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, toutes les pertes cerveau cycles de la pensée "getIsValid()" ou devrait-il être "isValid()" etc. peut être oublié. Je ne peux pas penser un seul moment que j'ai été sauvé d'un bug par un getter/setter.Il existe de nombreuses raisons. Mon préféré, c'est quand vous avez besoin de changer le comportement de réguler ou ce que vous pouvez définir sur une variable. Par exemple, disons que vous avez eu une setSpeed(int vitesse) de la méthode. Mais vous voulez que vous ne pouvez définir une vitesse maximale de 100. Vous feriez quelque chose comme:
Maintenant, si PARTOUT dans votre code vous avez été en utilisant le champ public et puis vous avez réalisé vous avez besoin de la condition ci-dessus? Ont plaisir de la chasse à chaque utilisation du domaine public au lieu de simplement modifier votre setter.
Mes 2 cents 🙂
while(speed < 200) { do_something(); accelerate(); }
)myCar.setSpeed(157);
et après quelques lignesspeed = myCar.getSpeed();
Et maintenant... je vous souhaite de joyeuses débogage, tout en essayant de comprendre pourquoispeed==100
quand il doit être157
Dans un pur monde orienté objet getters et setters est un terrible anti-modèle. Lire cet article: Des Getters/Setters. Mal. Période. En un mot, ils encourageons les développeurs à penser à des objets comme des structures de données, et ce type de pensée est pure de procédure (comme en COBOL ou C). Dans un langage orienté-objet il n'y a pas de structures de données, mais uniquement des objets qui exposent comportement (pas les attributs/propriétés!)
Vous pouvez trouver plus de détails dans la Section 3.5 de Élégant Objets (mon livre sur la programmation orientée objet).
new Dog()
n'est pas un chien. C'est l'objet qui contient des informations sur un chien. Et pour cette utilisation, il est naturel d'être en mesure de corriger d'une manière incorrecte poids enregistré.set…()
etget…()
, mais plutôtremember…()
ettell…()
. Juste que get et set est plus court à taper. En outre, un objet décrivant un autre objet, comme un papier de forme liée—devraient inclure dans le nom de la classe, mais c'est de nouveau la longue. Nous ne pouvons pas changer le poids du chien, et nous ne le faisons pas, ce que nous avons de changer le poids noté sur le chien formulaire de demande d'admission.Un avantage de accesseurs et des mutateurs, c'est que vous pouvez effectuer la validation.
Par exemple, si
foo
était public, je pourrais facilement le régler ànull
et puis quelqu'un d'autre pourrait essayer d'appeler une méthode sur l'objet. Mais il n'est plus là! Avec unsetFoo
méthode, je pourrais assurer quefoo
n'a jamais été mis ànull
.Des accesseurs et des mutateurs également permettre l'encapsulation - si vous n'êtes pas censé voir la valeur une fois son ensemble (peut-être qu'il est défini dans le constructeur et ensuite utilisé par des méthodes, mais jamais censé être changé), il n'aura jamais été vu par n'importe qui. Mais si vous pouvez permettre à d'autres classes pour les voir ou de les modifier, vous pouvez fournir le bon accesseur et/ou mutateur.
Dépend de votre langue. Vous avez marqués cette "orienté objet" plutôt que de "Java", donc je tiens à souligner que ChssPly76 la réponse est dépendant de la langue. En Python, par exemple, il n'y a pas de raison d'utiliser les accesseurs et mutateurs. Si vous avez besoin de changer le comportement, vous pouvez utiliser une propriété, qui s'enroule un getter et setter autour de la base de l'attribut d'accès. Quelque chose comme ceci:
obj.set_attr('foo')
) sont intrinsèquement supérieures à signes "égal" (obj.attr = 'foo'
). L'accès Public à accès public.obj.attr = 'foo'
juste définit la variable sans rien d'autre qui se passeobj.setAttr('foo')
"juste définit la variable sans rien d'autre qui se passe"? Si c'est un public de méthodes, alors il est une méthode publique. Si vous l'utilisez pour réaliser certains effets secondaires, et c'est public, alors vous feriez mieux d'être en mesure de compter sur tout travail comme si seul que prévu des effets secondaires qui s'est passé (avec tous d'autres détails de mise en œuvre et d'autres effets secondaires, l'utilisation des ressources, quelle que soit la, cachées à l'utilisateur de préoccupations). Ce n'est absolument pas différent avec Python. Python syntaxe pour obtenir l'effet est juste plus simple.Eh bien, je veux juste ajouter que même si ils sont parfois nécessaires pour l'encapsulation et la sécurité de vos variables/objets, si nous voulons le code d'un Objet réel Programme Orienté, alors nous avons besoin de ARRÊTER LE GASPILLAGE DE L'ACCESSEURS, provoquer parfois nous comptons beaucoup sur eux quand ils ne sont pas vraiment nécessaires et qui fait presque la même chose que si l'on met les variables publiques.
Merci, c'est vraiment précisé ma pensée. Voici maintenant (presque) 10 (presque) de bonnes raisons de ne PAS utiliser les accesseurs et mutateurs:
Les trois derniers, je suis juste de sortir (N/d ou D/C)...
Je sais c'est un peu tard, mais je pense qu'il y a certaines personnes qui sont intéressés à la performance.
J'ai fait un petit test de performance. J'ai écrit une classe "NumberHolder" qui, ainsi, est titulaire d'un Entier. Vous pouvez lire cet Entier à l'aide de la méthode de lecture
anInstance.getNumber()
ou en accédant directement le numéro à l'aideanInstance.number
. Mon programme lit le nombre 1 000 000 000 d'fois, par deux moyens. Ce processus est répété cinq fois, et le temps est imprimé. J'ai obtenu le résultat suivant:(Temps 1 est la voie la plus directe, de Temps 2 est le getter)
Vous le voyez, le getter est (presque) toujours un peu plus vite. Ensuite, j'ai essayé avec différents nombres de cycles. Au lieu de 1 million de dollars, j'ai utilisé 10 millions d'euros et 0,1 million de dollars.
Les résultats:
De 10 millions de cycles:
Avec 10 millions de cycles, les temps sont presque les mêmes.
Voici 100 mille dollars (0,1 million de cycles:
Également avec différentes quantités de cycles, de la lecture est un peu plus rapide que la façon habituelle. J'espère que cela vous a aidé.
Ne pas utiliser les accesseurs setters, sauf si nécessaire pour votre livraison I. e. Ne pas trop penser à ce qui pourrait arriver dans l'avenir, si une chose n'a changé son d'une demande de modification dans la plupart des applications de production, les systèmes d'.
Pensez simple, facile, ajouter de la complexité en cas de besoin.
Je ne voudrais pas profiter de l'ignorance des propriétaires d'une entreprise de profond savoir-faire technique, juste parce que je pense que c'est correct ou j'aime l'approche.
J'ai massive système écrit sans getters setters uniquement avec les modificateurs d'accès et de certaines méthodes pour valider les n effectuer biz logique. Si vous avez absolument besoin de l'. Utiliser quoi que ce soit.
J'ai passé un bon moment de penser ce fil pour le Java cas, et je crois que les vraies raisons sont:
En d'autres termes, la seule façon vous pouvez spécifier un champ dans une interface est de fournir une méthode pour écrire une nouvelle valeur et une méthode pour la lecture de la valeur actuelle.
Ces méthodes sont l'infâme getter et setter....
Il peut être utile pour le chargement différé. Dire que l'objet en question est stocké dans une base de données, et vous ne voulez pas aller le chercher si vous en avez besoin. Si l'objet est récupéré par un getter, puis l'objet interne peut être null jusqu'à ce que quelqu'un vous le demande, alors vous pouvez aller le chercher sur le premier appel à la lecture.
J'ai eu une page de base de la classe dans un projet qui m'a été remise qui était en train de charger des données à partir d'un couple de différents appels de service web, mais les données de ces appels de service web n'a pas toujours été utilisé dans toutes les pages enfant. Web services, pour tous les avantages, pionnier de nouvelles définitions de "ralentir", de sorte que vous ne voulez pas faire un appel de service web si vous n'avez pas à.
J'ai déménagé de champs publics pour les accesseurs, et maintenant les getters vérifier le cache, et si il n'y est pas d'appeler le service web. Donc, avec un peu d'habillage, beaucoup d'appels de service web ont été empêchés.
Donc de la lecture m'évite d'essayer de comprendre, sur chaque page enfant, ce que je vais avoir besoin. Si j'en ai besoin, j'appelle de la lecture, et il va le trouver pour moi si je ne l'est pas déjà.
Nous utilisons les getters et les setters:
Getter et setter sont les interfaces publiques à accès privé aux membres de la classe.
Encapsulation mantra
L'encapsulation mantra est de rendre les champs privés et les méthodes publiques.
Même si les getter et setter ne pas ajouter de nouvelles fonctionnalités, nous pouvons changer notre esprit de revenir plus tard pour faire de cette méthode
N'importe où une valeur peut être utilisée, une méthode qui renvoie cette valeur peut être ajoutée. Au lieu de:
utilisation
En d'autres termes
Supposons que nous avons besoin de stocker les détails de cette
Person
. CettePerson
a les champsname
,age
etsex
. En faisant cela implique la création de 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
une fois de plus.Au lieu de cela, nous pouvons créer un bean
class(Person)
avec les méthodes getter et setter. Donc, demain, il nous suffit de créer des objets de ce Beanclass(Person class)
chaque fois que nous avons besoin d'ajouter une nouvelle personne (voir la figure). Ainsi, nous sommes en réutilisant les champs et méthodes de classe d'haricot, ce qui est beaucoup mieux.Un aspect que j'ai manqué dans les réponses jusqu'à présent, la spécification d'accès:
Dans des langues qui ne supportent pas les "propriétés" (C++, Java) ou qui nécessitent une recompilation des clients lors de la modification de champs de propriétés (C#), à l'aide de méthodes get/set est plus facile à modifier. Par exemple, l'ajout d'une logique de validation à un setFoo méthode ne nécessite pas de modification de l'interface publique d'une classe.
Dans des langues qui soutien "réel" propriétés (Python, Ruby, peut-être Smalltalk?) il n'y a pas de point de méthodes get/set.
EDIT: j'ai répondu à cette question parce qu'il y a un tas de gens de l'apprentissage de la programmation en demandant cela, et la plupart des réponses sont techniquement très compétents, mais ils ne sont pas aussi facile à comprendre si vous êtes un débutant. Nous avons tous été débutants, donc je pensais que je voudrais essayer ma main à un plus débutant sympathique réponse.
Les deux principales sont le polymorphisme et la validation. Même si c'est juste un stupide structure de données.
Disons que nous avons cette classe simple:
Une classe très simple qui détient la quantité de liquide est en elle, et que sa capacité est de (en millilitres).
Ce qui se passe quand je fais:
Bien, vous ne seriez pas s'attendre à ce que de travailler, droit?
Que vous voulez être une sorte de test de cohérence. Et pire encore, que faire si je n'ai jamais précisé la capacité maximale? Oh, nous avons un problème.
Mais il y a un autre problème aussi. Que faire si les bouteilles ont été juste un type de conteneur? Que faire si nous avons eu plusieurs contenants, tous avec des capacités et des quantités de liquide rempli? Si nous pouvions juste une interface, nous pourrions laisser le reste de notre programme d'accepter que l'interface, et des bouteilles, des bidons d'essence et de toutes sortes de choses devaient travailler interchangably. Ne serait ce pas mieux? Depuis les interfaces de la demande des méthodes, c'est aussi une bonne chose.
Nous aimerions retrouver avec quelque chose comme:
Grand! Et maintenant, nous venons de changer la Bouteille à ceci:
Je vais laisser la définition de la BottleOverflowException comme un exercice pour le lecteur.
Maintenant, remarquez comment beaucoup plus robuste, c'est. Nous pouvons faire face à tout type de conteneur dans notre code maintenant en acceptant LiquidContainer au lieu de la Bouteille. Et comment ces bouteilles de traiter avec ce genre de choses peuvent être différents. Vous pouvez avoir des bouteilles que l'écriture de leur état sur le disque en cas de changement, ou de bouteilles que vous économisez sur les bases de données SQL ou GNU sait quoi d'autre.
Et tout cela peut avoir différentes façons de gérer les différentes whoopsies. La Bouteille vérifie juste et si il déborde, il jette une RuntimeException. Mais que peut-être la mauvaise chose à faire.
(Il est utile de débat à avoir sur la gestion des erreurs, mais je le garde, il est très simple ici sur le but. Les gens dans les commentaires seront susceptibles de pointer les défauts de cette approche simpliste. 😉 )
Et oui, il semble que nous allons partir d'une idée très simple à obtenir beaucoup mieux rapidement des réponses.
Veuillez noter également 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 la déclarant en finale. Mais si c'est une liste, vous pouvez la vider, ajouter des choses nouvelles, et ainsi de suite. Vous ne pouvez pas limiter l'accès à toucher les entrailles.
Il y a aussi la troisième chose que le monde n'a pas abordé: les accesseurs et mutateurs utiliser les appels de méthode. Cela signifie qu'ils ressemblent à des méthodes normales partout d'autre ne le fait. Au lieu d'avoir bizarre syntaxe spécifique pour les Dto et d'autres choses, vous avez la même chose partout.
L'une des principales bases de conception OO: Encapsulation!
Il vous donne de nombreux avantages, dont vous pouvez changer la mise en œuvre du getter/setter derrière les coulisses, mais les consommateurs de cette valeur va continuer à travailler aussi longtemps que le type de données reste la même.
À partir d'une orientation de l'objet point de vue design, les deux variantes peuvent être nocives pour la maintenance du code par l'affaiblissement de l'encapsulation des classes. Pour une discussion, vous pouvez regarder dans cet excellent article: http://typicalprogrammer.com/?p=23
Vous devez utiliser les accesseurs et mutateurs lorsque:
Donc, c'est très rarement un général OO question, c'est un langage spécifique à la question, avec des réponses différentes pour différentes langues (et les différents cas d'utilisation).
À partir d'un OO théorie de point de vue, les getters et les setters sont inutiles. L'interface de votre classe est ce qu'il fait, pas ce qu'elle est à l'état. (Si non, vous avez écrit à l'envers de la classe.) Dans des cas très simples, où la signification d'une classe n'est juste, par exemple, représentent un point en coordonnées rectangulaires,* les attributs font partie de l'interface; les getters et les setters juste nuage. Mais dans quoi que ce soit, mais des cas très simples, ni les attributs, ni les getters et les setters sont une partie de l'interface.
Mettre une autre façon: Si vous croyez que les consommateurs de votre classe ne doit même pas savoir que vous avez une
spam
attribut, encore moins être en mesure de le changer bon gré mal gré, en leur donnant unset_spam
méthode est la dernière chose que vous voulez faire.* Même pour cette classe simple, vous ne pouvez pas forcément envie de permettre la mise au
x
ety
valeurs. Si c'est vraiment une classe, ne devrait-il pas des méthodes commetranslate
,rotate
, etc.? Si c'est seulement une classe parce que votre langue n'ont pas de dossiers/struct/uplets nommé, alors ce n'est pas vraiment une question de OO...Mais personne n'en est jamais fait général OO design. Ils font la conception et la mise en œuvre, dans une langue spécifique. Et dans certaines langues, les getters et les setters sont loin d'être inutiles.
Si votre langue n'ont pas de propriétés, puis le seul moyen de représenter quelque chose qui est conceptuellement un attribut, mais est en fait calculé, ou validés, etc., est par des getters et les setters.
Même si votre langue n'ont des propriétés, il peut y avoir des cas où ils sont insuffisantes ou inappropriées. Par exemple, si vous souhaitez autoriser des sous-classes pour le contrôle de la sémantique d'un attribut, dans des langues sans accès dynamique, une sous-classe peut pas remplacer une propriété calculée pour un attribut.
Comme pour le "que faire si je veux changer de mise en œuvre plus tard?" question (qui est répété plusieurs fois dans différents formulation à la fois l'OP et l'on a accepté la réponse): Si c'est vraiment une pure mise en œuvre du changement, et que vous avez commencé avec un attribut, vous pouvez la changer en une propriété sans affecter l'interface. À moins, bien sûr, que votre langue ne supporte pas que. Donc c'est vraiment juste le même cas à nouveau.
Aussi, il est important de suivre les idiomes de la langue (ou le cadre) que vous utilisez. Si vous écrivez belle robe Rubis style de code en C#, tout expérimenté C# développeur d'autre que vous allez avoir des difficultés à le lire, et c'est mauvais. Certaines langues sont plus les cultures autour de leurs conventions que les autres.—et il ne peut pas être une coïncidence que Java et Python, qui sont sur les extrémités opposées du spectre de façon idiomatique getters sont, arrive d'avoir les deux plus forts cultures.
Au-delà de lecteurs humains, il y aura des bibliothèques et des outils qui attendent de vous que vous suivez les conventions, et faire de votre vie plus difficile si vous n'avez pas. L'accrochage de l'Interface du Générateur de widgets à rien mais ObjC propriétés, ou l'utilisation de certains Java se moquant de bibliothèques sans getters, est tout simplement faire de votre vie plus difficile. Si les outils sont importants pour vous, ne les combattez pas.
Getter et setter sont des méthodes d'accès, ce qui signifie qu'ils sont généralement d'une interface publique pour modifier privé des membres de la classe. Vous utilisez les méthodes getter et setter pour définir une propriété. Vous accédez à getter et setter comme des propriétés à l'extérieur de la classe, même si vous les définir dans la classe en tant que méthodes. Ces propriétés en dehors de la classe peut avoir un nom différent du nom de la propriété dans la classe.
Il y a des avantages à utiliser les méthodes getter et setter, telles que la capacité pour vous permettre de créer des membres, avec des fonctionnalités que vous pouvez accéder à des propriétés similaires. Ils vous permettent également de créer en lecture seule et en écriture seule propriétés.
Même si les méthodes getter et setter sont utiles, vous devez être prudent de ne pas en abuser parce que, entre autres questions, ils peuvent faire de la maintenance du code plus difficile dans certaines situations. Aussi, ils fournissent l'accès à votre implémentation de la classe, comme les membres du public. La programmation orientée objet la pratique décourage un accès direct aux propriétés à l'intérieur d'une classe.
Lorsque vous écrivez des classes, vous encourage à en faire autant que possible de vos variables d'instance privée et ajouter des accesseurs et des mutateurs en conséquence. C'est parce qu'il y a plusieurs moments où vous ne voulez pas pour permettre aux utilisateurs de modifier certaines variables dans vos classes. Par exemple, si vous avez une méthode statique qui suit le nombre d'instances créées pour une classe spécifique, vous ne voulez pas qu'un utilisateur de modifier le compteur à l'aide de code. Seul le constructeur déclaration doit incrémenter la variable à chaque fois qu'il appelle. Dans cette situation, vous pouvez créer une instance privée variable et de permettre une méthode de lecture uniquement pour la variable compteur, ce qui signifie que les utilisateurs sont en mesure de récupérer la valeur actuelle uniquement à l'aide de la méthode de lecture, et ils ne seront pas en mesure de définir de nouvelles valeurs à l'aide de la méthode d'initialisation. La création d'un getter sans un setter est une simple façon de faire de certaines variables dans votre classe en lecture seule.
Code évolue.
private
est idéal pour quand vous avez besoin d'un membre de données de protection. Finalement, toutes les classes doivent être sorte de "miniprograms" qui ont une interface bien définie, que vous ne pouvez pas juste vis avec le fonctionnement interne de.Cela dit, de développement de logiciels n'est pas à propos de la mise bas que la version finale de la classe, comme si vous étiez en appuyant sur la fonte de la statue sur le premier essai. Pendant que vous travaillez avec elle, le code est plus comme de l'argile. Il évolue comme vous le développer et d'en apprendre plus sur le domaine du problème à résoudre. Au cours du développement des classes peuvent interagir les uns avec les autres que ce qu'ils devraient (dépendance que vous prévoyez de facteur), fusionner ou séparer. Je pense donc que le débat se résume à des gens qui ne veulent pas religieusement écrire
De façon à avoir:
Au lieu de
N'est pas seulement
getVar()
visuellement bruyant, il donne cette illusion quegettingVar()
est en quelque sorte un processus plus complexe qu'il ne l'est vraiment. Comment vous (comme la classe écrivain) concernant le caractère sacré de lavar
est particulièrement déroutant pour un utilisateur de votre classe, si il a un genre de setter -- puis on dirait que vous êtes de mettre en place ces portes afin de "protéger" quelque chose vous insistez est précieux, (le caractère sacré de lavar
), mais encore vous le concèdevar
protection ne vaut pas beaucoup par la possibilité pour quiconque de juste venir etset
var
à la valeur qu'il veut, sans même jeter un oeil à ce qu'ils font.Donc je programme comme suit (en supposant un "agile approche de type" -- c'est à dire quand j'écris du code ne sachant pas exactement ce qu'il en sera de faire/ne pas avoir le temps ou l'expérience de plan d'élaborer une cascade de style de l'interface set):
1) Commencez avec tous les membres du public pour les objets de base de données avec des données et le comportement. C'est pourquoi, dans tout mon C++ "exemple de code", vous remarquerez que je l'utilise
struct
au lieu declass
partout.2) Lorsqu'un objet interne de comportement pour un membre de données devient assez complexe (par exemple, il aime garder un intérieur
std::list
dans un certain ordre), accesseur type de fonctions sont écrites. Parce que je suis de programmation par moi-même, je n'ai pas toujours définir le membreprivate
tout de suite, mais quelque part en bas de l'évolution de la classe, le membre sera "promu" à uneprotected
ouprivate
.3) les Classes qui sont bien définis et ont des règles strictes concernant leurs internes (c'est à dire ils savent exactement ce qu'ils font, et vous n'êtes pas à "baiser" (terme technique) avec ses internes) sont donnés à la
class
désignation, par défaut les membres privés, et seule une poignée de membres sont autorisés à êtrepublic
.Je trouve cette approche me permet d'éviter de rester assis là et religieusement écriture lecture/définition lorsqu'un grand nombre de données de membres qui ont migré hors, décalé, etc ... durant les premiers stades d'une classe de l'évolution.
Il y a une bonne raison d'envisager l'utilisation des accesseurs est la propriété de l'héritage. Voir l'exemple suivant:
De sortie:
Getters et setters sont utilisés pour mettre en œuvre deux des aspects fondamentaux de la Programmation Orientée Objet, qui sont:
Supposons que nous ayons une classe d'Employés:
Ici les détails de mise en œuvre de Nom Complet est caché de l'utilisateur et n'est pas accessible directement à l'utilisateur, à la différence d'un attribut public.
Une autre utilisation (dans des langues qui prennent en charge les propriétés), c'est que les setters et getters peut impliquer qu'une opération est non-trivial. En général, vous voulez éviter de faire tout ce qui est gourmand en ressources dans une propriété.
execute
oubuild
méthode.Relativement moderne avantage de getters/setters est c'est fait, il est plus facile de parcourir le code dans étiqueté (indexée) des éditeurs de code. E. g. Si vous voulez voir qui définit un membre, vous pouvez ouvrir la hiérarchie d'appel de l'incubateur.
D'autre part, si le membre est public, les outils ne permettent pas possible de filtrer les accès en lecture/écriture pour le membre. Donc, vous avez à crapahuter si toutes les utilisations du membre.
Dans un langage orienté objet, les méthodes, et leurs modificateurs d'accès, de déclarer l'interface de l'objet. Entre le constructeur et l'accesseur et mutateur méthodes, 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ée public, alors il n'y a aucun moyen de réguler l'accès.
Et quand nous sommes à l'aide de setters nous pouvons restreindre l'utilisateur pour l'entrée nous avons besoin. Signifier le nourrir pour qu'très variable viendra par un bon canal et le canal est prédéfini par nous. Il est donc plus sûr d'utiliser des organismes de normalisation.
En outre, c'est à "l'avenir" de votre classe. En particulier, la modification d'un champ à un bien immobilier est une ABI pause, donc si vous ne décidez plus tard que vous avez besoin de plus logique que de simplement "set/get le terrain", alors vous avez besoin pour briser ABI, qui, bien sûr, crée des problèmes pour quoi que ce soit d'autre est déjà compilé avec votre classe.
Je voudrais juste lancer l'idée de l'annotation : @getter et @setter. Avec @getter, vous devriez être en mesure d'obj = la classe.champ, mais pas de classe.champ = obj. Avec @setter, et vice versa. Avec @getter et @définition, vous devriez être en mesure de faire les deux. Cela permettrait de préserver l'encapsulation et de réduire le temps en ne demandant pas des méthodes triviales au moment de l'exécution.
Je ne peux penser à une raison pourquoi vous ne voulez pas seulement tout public.
Par exemple, la variable que vous avez jamais eu l'intention de l'utiliser en dehors de la classe pourrait être accessible, même irdirectly par une chaîne variable d'accès (c'est à dire de l'objet.de l'élément.de l'origine.x ).
En ayant la plupart du temps tout privé, et seulement les choses que vous voulez étendre et, éventuellement, reportez-vous à la dans les sous-classes protégées, et n'ayant static final des objets en tant que public, alors vous pouvez contrôler ce que d'autres programmeurs et les programmes peuvent utiliser dans l'API et ce qu'il peut accéder et qu'il ne peut pas en utilisant les setters et getters pour accéder à la substance que vous voulez que le programme, ou peut-être d'autres programmeurs qui vient de se produire pour utiliser votre code, peut modifier dans votre programme.
circ.radius
ne l'est pas. Cependant, get_diameter(), get_circumference() et get_area() peut effectuer des calculs basés sur le rayon. Sans getters, vous devez effectuer les calculs vous-même et vérifier que vous avez droit.Comme un exemple:
Si vous créez une variable publique, vous pouvez accéder à cette variable et la valeur de changement de n'importe où(toute la classe). Mais si vous créez en tant privé que la variable ne peut pas voir et accéder à toute la classe sauf déclaré classe.
Alors, comment peut-on accéder à cette variable à l'extérieur:
C'est l'endroit getters et setters en venir. Vous pouvez déclarer la variable comme privé, alors vous pouvez mettre en œuvre des méthodes getter et setter pour cette variable.
Exemple(Java):
Avantage:
Quand quelqu'un veut-il de l'accès ou de modifier/définir la valeur à
balance
variable, il/elle doit avoir la permision.Vous pouvez définir la valeur dans le constructeur aussi mais quand, plus tard, quand vous voulez
pour mettre à jour/changement de la valeur, vous devez implémenter la méthode d'initialisation.
Je voulais poster un exemple concret j'ai tout juste terminé:
fond - je hibernate des outils pour générer les mappages pour ma base de données, une base de données que je suis l'évolution que je développe. J'ai changer le schéma de base de données, pousser les modifications, puis exécutez hibernate des outils pour générer le code java. Tout est bien et bon jusqu'à ce que je veux ajouter des méthodes à correspond à des entités. Si je modifie les fichiers générés, ils seront écrasés à chaque fois que je fais une modification de la base de données. J'ai donc étendre les classes générées comme ceci:
Ce que j'ai fait ci-dessus est de remplacer les méthodes existantes sur la super classe avec mes nouvelles fonctionnalités (quelque chose+1) sans jamais toucher la classe de base. Même scénario si vous avez écrit une classe il y a un an et que vous voulez aller à la version 2 sans modifier vos classes de base (test de cauchemar). espérons que cela aide.
Je vais laisser le code parle de lui-même:
En pensez-vous? Voici les setters:
Si vous voulez une variable en lecture seule, mais ne veulent pas le client d'avoir à changer la manière dont ils accèdent, essayez ce basé sur un modèle de classe:
Exemple D'Utilisation:
Rappelez-vous, vous aurez besoin d'ajouter au niveau du bit et des opérateurs unaires ainsi! C'est juste pour vous obtenir a commencé
Relativement moderne avantage de getters/setters est c'est fait, il est plus facile de parcourir le code dans étiqueté (indexée) des éditeurs de code. E. g. Si vous voulez voir qui définit un membre, vous pouvez ouvrir la hiérarchie d'appel de l'incubateur.
D'autre part, si le membre est public, les outils ne permettent pas possible de filtrer les accès en lecture/écriture pour le membre. Donc, vous avez à crapahuter si toutes les utilisations du membre.
Bien que n'étant pas commun pour les getter et setter, l'utilisation de ces méthodes peuvent aussi être utilisées dans des AOP/modèle de proxy utilise.
par exemple pour la vérification de la variable, vous pouvez utiliser l'AOP à la vérification de mise à jour de la valeur.
Sans getter/setter il n'est pas possible, sauf changer le code partout.
Personnellement je n'ai jamais utilisé l'AOP pour cela, mais il montre un avantage de l'utilisation de getter/setter.
C'est une bonne question, même avec la meilleure des réponses. Comme il ya beaucoup d'entre eux, je vais juste y mettre un peu plus
Cet exemple est basé sur le C#, juste une pièce utile de code. La validation des données dans les crochets ont été déjà expliqué.