1854 votes

Pourquoi utiliser les accesseurs et mutateurs?

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.


La compilation de la liste jusqu'ici au-dessus de ce qui semblait gagnants pour moi, du point de vue de Java web dev:

  1. Lorsque vous réalisez que vous avez besoin de faire plus que simplement définir et à obtenir la valeur, vous n'avez pas à modifier chaque fichier dans la base de code.
  2. Vous pouvez effectuer la validation ici.
  3. Vous pouvez modifier la valeur définie.
  4. Vous pouvez masquer la représentation interne. getAddress() pourrait en fait être l'obtention de plusieurs champs pour vous.
  5. Vous avez isolé de votre interface publique de changements sous les draps.
  6. Certaines bibliothèques s'attendre à ce. La réflexion, la sérialisation, les objets fantaisie.
  7. Héritant de cette classe, vous pouvez remplacer les fonctionnalités par défaut.
  8. Vous pouvez avoir différents niveaux d'accès pour les getter et setter.
  9. Chargement différé.
  10. Les gens peuvent facilement vous dire de ne pas utiliser Python.

1205voto

LBushkin Points 60611

Il ya effectivement beaucoup de bonnes raisons d'envisager d'utiliser les 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.

Voici quelques-unes des raisons pour lesquelles je suis conscient de:

  • L'Encapsulation de comportement associé à l'obtention ou à la définition de la propriété - ce qui permet à des fonctionnalités supplémentaires (comme la validation) à ajouter plus facilement plus tard.
  • Le masquage de la représentation interne de la propriété, tout en exposant une propriété à l'aide d'une variante de la représentation.
  • L'isolation de votre interface publique de changement - en permettant à l'interface publique à rester constante, tandis que la mise en œuvre des modifications sans affecter les consommateurs existants.
  • Le contrôle de la durée de vie et la gestion de la mémoire (élimination) de la sémantique de la propriété - particulièrement important dans la non-mémoire gérée environnements (comme C++ ou Objective-C).
  • Fournir un débogage interception point lors de la modification d'une propriété à l'exécution de débogage quand et où un bien changé pour une valeur particulière peut être assez difficile sans cela, dans certaines langues.
  • L'amélioration de l'interopérabilité avec les bibliothèques qui sont conçus pour fonctionner à l'encontre de la propriété de lecture/définition - Moqueur, la Sérialisation, et WPF viennent à l'esprit.
  • Permettant aux héritiers de changer la sémantique de la façon dont la propriété se comporte et est exposée en substituant les getter/setter.
  • Permettant le getter/setter pour être passée autour d'expressions lambda plutôt que de valeurs.
  • Les accesseurs et mutateurs peut permettre différents niveaux d'accès - par exemple l'obtenir peut être public, mais l'ensemble pourrait être protégé.

632voto

ChssPly76 Points 53452

Parce que 2 semaines (mois, années) à partir de maintenant, lorsque vous vous rendez compte que votre setter a besoin de faire plus que de simplement définir la valeur, vous pourrez aussi réaliser que la propriété a été utilisée directement dans 238 autres classes :-)

445voto

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é.

Un 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:

class Foo {
public:
    int DaysLeft;
    int ContestantNumber;
}

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.

Client: "Que puis-je faire avec un objet de cette classe?"
Designer: "Vous pouvez lire et écrire plusieurs variables."
Client: "Oh... cool, je suppose?"

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 (you Ain't Gonna Besoin).

118voto

Kai Points 4954

Beaucoup de gens parlent 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 venez à travers ce:

person.name = "Joe";

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.

50voto

Moshe Levi Points 2084

Eh bien, cela semble être le bon endroit pour citer une drôle de post intitulé "Salope Types" de Davy Brion blog.

Salope Types sont des types qui:

  1. vous donner accès à leurs soldats sans trop de difficultés
  2. ne vous souciez pas vraiment au sujet de vos intentions, ou s'ils le font, ne sont pas très clair sur ce
  3. parfois sembler une bonne correction à court terme
  4. peut être utilisé dans une variété de façons, avec des résultats différents, et aucun de elles sont garantis
  5. ne peut pas faire confiance
  6. vraiment besoin d'être testé
  7. vous brûle, tôt ou tard, si vous ne faites pas attention
  8. deviennent encore plus de désordre pendant le processus de vieillissement

C'est une drôle de façon de vous dire pourquoi vous devriez utiliser l'encapsulation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X