J'ai une classe avec une variable qui est privée et la classe a un getter et un setter pour cette variable. Pourquoi ne pas rendre cette variable publique?
Le seul cas, je pense que vous devez utiliser des getters et setters, c'est si vous avez besoin de faire une opération en plus de l'ensemble ou du get. Exemple:
void my_class::set_variable(int x){
/* Some operation like updating a log */
this->variable = x;
}
this->variable = x + 5
, ou appeler uneUpdateStatistics
fonction dans setter, et dans ces cas,classinstancea->variable = 5
cela causera des problèmes.set_inch
,set_centimeter
,get_inch
,get_centimeter
, avec quelques actions fantasmagoriques.Réponses:
Avez-vous déjà entendu parler d'une propriété?
Une propriété est un champ qui a des accesseurs "intégrés" (getters et setters). Java, par exemple, n'a pas de propriétés, mais il est recommandé d'écrire les getters et setters dans un champ privé. C # a des propriétés.
Alors, pourquoi avons-nous besoin de getters et de setters? Fondamentalement, nous en avons besoin pour protéger / protéger le champ. Par exemple, vous n'accédez pas au champ en référence mémoire, vous accédez à une méthode qui changera ensuite le champ (référence). Cette méthode est capable d'effectuer certaines opérations qu'un utilisateur n'est pas disposé à connaître ( comportement d'encapsulation ), comme dans votre exemple. Imaginez, par exemple, qu'une douzaine de classes utilisent votre champ public et que vous devez changer la façon dont il est utilisé ... Vous devez regarder chacune de ces classes afin de changer la façon dont elles utilisent le champ ... Non donc "OOlysh".
Mais, par exemple, si vous avez un champ booléen appelé mort. Vous devriez réfléchir à deux fois avant de déclarer un setDead et isDead. Vous devez écrire des accesseurs lisibles par l'homme , par exemple, kill () au lieu de setDead.
Cependant, il existe de nombreux frameworks qui supposent que vous suivez la convention de nommage JavaBean (en parlant de Java ici), par conséquent, dans ces cas, vous devez déclarer tous les getters et setters après la convection de nommage.
la source
foo.bar = biz.baz+5
appeler une fonctionbiz
à évaluerbaz
, puis d'en ajouter cinq et d'appeler une fonctionfoo
pour définirbar
la valeur résultante. Ces surcharges ne sont pas appelées «propriétés», mais elles peuvent servir le même objectif.Ce n'est pas l'opinion la plus populaire mais je ne vois pas beaucoup de différence.
Les setters et les getters sont une assez mauvaise idée. J'y ai pensé et honnêtement, je ne peux pas trouver de différence entre un setter / getter une propriété et une variable publique dans la pratique.
Dans THEORY, un setter et un getter ou une propriété ajoutent un endroit pour effectuer des actions supplémentaires lorsqu'une variable est définie / obtenue et en théorie, ils isolent votre code des modifications.
En réalité, je vois rarement des setters et des getters utilisés pour ajouter une action, et lorsque vous voulez ajouter une action, vous voulez l'ajouter à TOUS les setters ou getters d'une classe (comme la journalisation), ce qui devrait vous faire penser qu'il devrait y avoir être une meilleure solution.
En ce qui concerne l'isolement des décisions de conception, si vous changez un int en un long, vous devez toujours changer vos setters et vérifier au moins chaque ligne qui y accède à la main - pas beaucoup d'isolement là-bas.
Les classes mutables doivent être évitées par défaut de toute façon, donc l'ajout d'un setter devrait être un dernier recours. Ceci est atténué avec le modèle de générateur où une valeur peut être définie jusqu'à ce que l'objet soit dans l'état souhaité, puis la classe peut devenir immuable et vos setters lèveront des exceptions.
En ce qui concerne les getters - je ne peux toujours pas trouver une grande différence entre un getter et une variable finale publique. Le problème ici est que c'est mauvais OO dans les deux cas. Vous ne devriez pas demander une valeur à un objet et opérer dessus - vous devriez demander à un objet d'effectuer une opération pour vous.
Soit dit en passant, je ne préconise en aucun cas les variables publiques - je dis que les setters et les getters (et même les propriétés) sont bien trop proches des variables publiques.
Le gros problème est simplement que les gens qui ne sont pas des programmeurs OO sont trop tentés d'utiliser des setters et des getters pour transformer des objets en propriétés (structures) qui sont transmises et exploitées, à peu près le contraire du fonctionnement du code orienté objet.
la source
L'utilisateur de getters et setters entre dans le principe de l' encapsulation . Cela vous permettra de changer la façon dont les choses fonctionnent à l'intérieur de la classe et de garder tout fonctionne.
Par exemple, si 3 autres objets appellent
foo.bar
pour obtenir la valeur de la barre et que vous décidez de changer le nom de la barre, vous avez un problème. Si les objets appelés,foo.bar
vous devrez changer toutes les classes qui ont ceci. Si un setter / getter est utilisé, vous n'avez rien à changer. Une autre possibilité consiste à changer le type de la variable, auquel cas il suffit d'ajouter du code de transformation au getter / setter et tout va bien.la source
L'utilisation de getters et setters vous permet également de contrôler le contenu stocké dans une variable particulière. Si le contenu doit être d'un certain type ou d'une certaine valeur, une partie de votre code de définition peut être de garantir que la nouvelle valeur répond à ces exigences. Si la variable est publique, vous ne pouvez pas vous assurer que ces exigences sont remplies.
Cette approche rend également votre code plus adaptable et gérable. Il est beaucoup plus facile d'apporter des modifications à l'architecture d'une classe si vous avez des fonctions en place qui gardent cette architecture cachée de toutes les autres classes ou fonctions qui utilisent cette classe. Le changement déjà mentionné d'un nom de variable n'est que l'un des nombreux changements qui sont beaucoup plus faciles à effectuer si vous avez des fonctions comme les getters et les setters. L'idée générale est de garder le plus de confidentialité possible, en particulier vos variables de classe.
la source
Vous dites "Le seul cas où je pense que vous devez utiliser des getters et setters est si vous avez besoin de faire une opération en plus du set ou du get".
Vous devriez utiliser des getters et setters si à un moment donné dans le futur vous pourriez avoir besoin de faire une opération en plus de l'ensemble et d'obtenir et que vous ne voulez pas changer des milliers de lignes de code source lorsque cela se produit.
Vous devez utiliser des getters et setters si vous ne voulez pas que quelqu'un prenne l'adresse de la variable et la transmette, avec des conséquences désastreuses si cette variable peut ensuite être modifiée sans que le code source le mentionne, ou même après que l'objet a cessé d'exister. .
la source
Tout d'abord, soyons clairs sur le paradigme.
Où un getter / setter est-il utile?
Les getters / setters sont-ils utiles dans les structures de données? Non.
Une structure de données est une spécification de disposition de mémoire qui est commune et manipulée par une famille de fonctions.
Généralement, toute ancienne fonction nouvelle peut venir et manipuler une structure de données, si elle le fait de manière à ce que les autres fonctions puissent toujours la comprendre, alors la fonction rejoint la famille. Sinon, c'est une fonction escroc et une source de bugs.
Ne vous méprenez pas, il pourrait y avoir plusieurs familles de fonctions qui se disputent cette structure de données avec des snitches, des turn-coats et des agents doubles partout. C'est bien quand ils ont chacun leur propre structure de données pour jouer, mais quand ils la partagent ... imaginez simplement plusieurs familles criminelles en désaccord sur la politique, cela peut devenir un gâchis très rapidement.
Étant donné le désordre que les familles de fonctions étendues peuvent atteindre, existe-t-il un moyen de coder la structure des données afin que les fonctions non autorisées ne gâchent pas tout? Oui, ils sont appelés objets.
Les getters / setters sont-ils utiles dans les objets? Non.
L'intérêt de regrouper une structure de données dans un objet était de garantir qu'aucune fonction non autorisée ne pouvait exister. Si la fonction voulait rejoindre la famille, elle devait d'abord être soigneusement examinée, puis faire partie de l'objet.
Le but / but d'un getter et d'un setter est de permettre à des fonctions en dehors de l'objet de modifier directement la disposition de la mémoire de l'objet. Cela ressemble à une porte ouverte pour permettre aux voyous ...
The Edge Case
Il y a deux situations où un getter / setter public avait du sens.
Les conteneurs et les interfaces de conteneurs sont des exemples parfaits de ces deux situations. Le conteneur gère les structures de données (liste liée, carte, arborescence) en interne, mais donne le contrôle de l'élément spécifique à tout le monde. L'interface résume cela et ignore complètement l'implémentation et décrit uniquement les attentes.
Malheureusement, de nombreuses implémentations se trompent et définissent l'interface de ces sortes d'objets pour donner un accès direct à l'objet réel. Quelque chose comme:
C'est cassé. Les implémentations de Container doivent explicitement remettre le contrôle de leurs composants internes à quiconque les utilise. Je n'ai pas encore vu un langage à valeur mutable où cela soit bien (les langages avec une sémantique à valeur immuable sont par définition bien du point de vue de la corruption des données, mais pas nécessairement du point de vue de l'espionnage des données).
Vous pouvez améliorer / corriger les getters / setter en utilisant uniquement la copie sémantique, ou en utilisant un proxy:
On peut soutenir qu'une fonction escroc pourrait encore jouer au chaos ici (avec assez d'efforts, la plupart des choses sont possibles), mais la copie sémantique et / ou le proxy réduisent les risques d'erreurs.
Getters / Setters privés
Il s'agit du dernier bastion de getters et setters travaillant directement sur le type. En fait, je n'appellerais même pas ces getters et setters mais des accesseurs et des manipulateurs.
Dans ce contexte, la manipulation d'une partie spécifique de la structure de données nécessite parfois / presque toujours / généralement une tenue de livres spécifique. Supposons que lorsque vous mettez à jour la racine d'une arborescence, le cache de surveillance doit être purgé, ou lorsque vous accédez à l'élément de données externe, un verrou doit être obtenu / libéré. Dans ces cas, il est logique d'appliquer le principal DRY et de répartir ces actions ensemble.
Dans le contexte privé, il est toujours possible pour les autres fonctions de la famille de contourner ces «getters et setters» et de manipuler la structure des données. C'est pourquoi je les considère davantage comme des accesseurs et des manipulateurs. Vous pouvez accéder directement aux données ou compter sur un autre membre de la famille pour obtenir cette partie correctement.
Getters / Setters protégés
Dans un contexte protégé, ce n'est pas très différent d'un contexte public. Les fonctions étrangères éventuellement escrocs veulent accéder à la structure de données. Donc non, s'ils existent, ils fonctionnent comme des getters / setters publics.
la source
De l'expérience C ++, le setter / getter est utile pour 2 scénarios:
En dehors de cela, la sécurité est un point valable mais son importance est limitée à très peu d'applications de développement comme les modules liés à la connexion ou à l'accès à la base de données. Pourquoi s'embêter à coder en plus quand peu de gens utilisent votre module?
la source