J'ai une classe avec une variable privée et la classe a un getter et un setter pour cette variable. Pourquoi ne pas faire cette variable publique?
Le seul cas, je pense que vous devez utiliser des getters et des setters est si vous avez besoin de faire une certaine opération en plus de l'ensemble ou de l'obtention. Exemple:
void my_class::set_variable(int x){
/* Some operation like updating a log */
this->variable = x;
}
Avez-vous déjà entendu parler d'une propriété?
Une propriété est un domaine qui a des "accompagnés" d'accessoires (getters et setters intégrés). Java, par exemple, n'a pas de propriétés, mais il est recommandé d'écrire les getters et les configurateurs dans un domaine privé. C # a des propriétés.
Alors, pourquoi avons-nous besoin de getters et de setters? Fondamentalement, nous en avons besoin de protection/bouclier le champ. Par exemple, vous n'accédez pas au champ en référence de la 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é à savoir (Comportement encapsulant), comme dans votre exemple. Imaginez, par exemple, qu'une douzaine de classes utilisent votre domaine public et que vous devez changer la façon dont il est utilisé ... vous devriez regarder chacune de ces classes afin de changer la façon dont ils utilisent le champ ... pas alors "oolysh".
Mais, par exemple, si vous avez un champ booléen appelé mort. Vous devriez réfléchir à deux fois avant de déclarer une Endread et Isdead. Vous devriez écrire des accesseurs qui sont Lisible humain, par exemple, tuer () au lieu de SetDead.
Cependant, il existe de nombreux cadres qui supposent que vous suivez la Convention de nommage JavaBean (parle de Java ici), par conséquent, dans ces cas, vous devriez déclarer tous les getters et setters suivant la Nommer la convétion.
Ce n'est pas l'opinion la plus populaire mais je ne vois pas une grande partie de la différence.
Les setters et les getters sont une idée assez mauvaise. J'y ai pensé et honnêtement, je ne peux pas trouver une différence entre un setter/getter une propriété et une variable publique dans la pratique.
En théorie, un setter et un getter ou une propriété ajoutent un endroit pour prendre des mesures 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 ensembles et des getters utilisés pour ajouter une action, et lorsque vous souhaitez ajouter une action, vous souhaitez l'ajouter à toutes les configurations ou getters d'une classe (comme la journalisation) qui devrait vous faire penser qu'il devrait faire être une meilleure solution.
En ce qui concerne les décisions de conception isolant, si vous modifiez un INT vers une longue, vous devez toujours modifier vos releveurs et au moins vérifier toutes les lignes qui les accède à la main - pas beaucoup d'isolement là-bas.
De toute façon, les classes mutables doivent être évitées de toute façon, l'ajout d'un seigteur devrait donc être un dernier recours. Ceci est atténué avec le motif de constructeur où une valeur peut être réglée jusqu'à ce que l'objet soit dans l'état souhaité, la classe peut devenir immuable et vos relevoirs lanceront des exceptions.
Quant aux getters - je ne peux toujours pas trouver une grande partie de la différence entre une variable de 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 d'un objet et vous y opérer - vous devez demander à un objet de faire une opération pour vous.
En passant, je ne préconise en rien des variables publiques - je dis que je dis que des sécheurs et des getters (et même des propriétés) sont beaucoup trop proches pour être déjà des variables publiques.
Le gros problème est simplement que les personnes qui ne soient pas OO _ Les programmeurs sont trop tentés pour utiliser des setters et gettent de faire des objets dans des boules de propriété (structures) transmises et utilisées, à peu près le contraire de Comment fonctionne le code orienté objet.
L'utilisateur de getters et de setters passe dans le principe de 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 vous décidez de changer le nom de la barre à votre place, vous avez un problème sur vos mains. Si les objets appelés foo.bar
Vous devriez changer toutes les classes qui ont cela. Si un setter/getter est utilisé, vous n'avez rien à changer. Une autre possibilité est de modifier le type de variable dans ce cas, ajoutez simplement un code de transformation sur le getter/Setter et vous allez bien.
L'utilisation de getters and Setters vous permet également de contrôler quel contenu est stocké dans une variable particulière. Si le contenu doit être d'un certain type ou une certaine valeur, une partie de votre code de réglage peut être de veiller à ce que la nouvelle valeur réponde à 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 de modifier 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 qu'un de nombreux changements qui sont beaucoup plus faciles à faire si vous avez des fonctions telles que des getters et des setters. L'idée générale est de garder le plus grand public possible, en particulier de vos variables de classe.
Vous dites "le seul cas, je pense que vous devez utiliser des getters et des setters est si vous devez faire une certaine opération en dehors de l'ensemble ou de l'obtention.".
Vous devez utiliser des getters et des setters si à un moment donné dans le futur, vous WORI besoin de faire une certaine opération en plus de l'ensemble et d'obtenir et vous ne souhaitez pas modifier des milliers de lignes de code source lorsque cela se produit.
Vous devez utiliser des getters and Setters si vous ne voulez pas que quelqu'un prenne l'adresse de la variable et la transmettez-la, avec des conséquences désastreuses si cette variable peut ensuite être modifiée sans aucun code source le mentionnant, ou même après l'arrêt de l'objet existant. .
Tout d'abord, soyez clair sur le paradigme.
où est utile un getter/setter?
Les getters/setters sont-ils utiles dans les structures de données? no.
Une structure de données est une spécification de présentation de la mémoire commune et manipulée par une famille de fonctions.
Généralement, toute nouvelle fonction neuve peut venir et manipuler une structure de données, si elle le fait de manière à ce que les autres fonctions puissent la comprendre, la fonction rejoint la famille. Sinon, c'est une fonction de voyous et une source de bugs.
Ne vous méprenez pas, il pourrait y avoir plusieurs familles de fonctions en guerre sur cette structure de données avec des tournants, des retournements et des doubles agents partout partout. Son amende quand ils ont chacun leur propre structure de données à jouer, mais quand ils le partagent ... Imaginez simplement plusieurs familles de crimes en désaccord sur la politique, cela peut devenir un désordre vraiment rapide.
Compte tenu des familles de fonctions étendues de mess pouvant atteindre, est-il un moyen d'encoder la structure de données afin que les fonctions de voyous ne plaisent pas tout de suite? Oui, ils sont appelés objets.
Les getters/setters sont-ils utiles dans des objets? no.
L'ensemble du point d'envelopper une structure de données dans un objet était de garantir qu'aucune fonction de voyou pourrait exister. Si la fonction voulait rejoindre la famille, il devait d'abord être soigneusement vérifié, puis de devenir une partie de l'objet.
Le point/but d'un getter et d'un setter consiste à autoriser des fonctions en dehors de l'objet de modifier directement la disposition de la mémoire de l'objet directement. qui ressemble à une porte ouverte pour permettre aux voleurs ...
le boîtier de bord
Il y a deux situations. Un getter/setter public a un 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 contrôle des mains sur l'élément spécifique à tous et à divers. L'interface résumait cela et ignore entièrement la mise en œuvre et décrit uniquement les attentes.
Malheureusement, de nombreuses implémentations obtiennent ce problème et définissent l'interface de ces sortes d'objets pour donner un accès direct à l'objet réel. Quelque chose comme:
interface Container<T>
{
typedef ...T... TRef; //<somehow make TRef to be a reference or pointer to the memory location of T
TRef item(int index);
}
C'est cassé. Les implémentations de conteneur doivent explicitement contrôler leurs internes à quiconque les utilisent. Je n'ai pas encore vu une langue de valeur mutable où cela va bien (les langues avec une sémantique immuable-valeur sont par définition d'une perspective de corruption de données, mais pas nécessairement d'une perspective d'espionnage de données).
Vous pouvez améliorer/corriger les getters/setter en utilisant uniquement la sémantique de copie ou en utilisant un proxy:
interface Proxy<T>
{
operator T(); //<returns a copy
... operator ->(); //<permits a function call to be forwarded to an element
Proxy<T> operator=(T); //< permits the specific element to be replaced/assigned by another T.
}
interface Container<T>
{
Proxy<T> item(int index);
T item(int index); //<When T is a copy of the original value.
void item(int index, T new_value); //<where new_value is used to replace the old value
}
Sans doute, une fonction malhonnête pourrait encore jouer à Mayhem ici (avec suffisamment d'efforts que la plupart des choses sont possibles), mais la sémantique de copie et/ou le proxy réduit les chances pour un certain nombre d'erreurs.
getters privés/setters
C'est le dernier bastion de getters et de setters travaillant directement sur le type. En fait, je n'appellerais même pas ces getters et setters, mais les accesseurs et les manipulateurs.
Dans ce contexte, la manipulation parfois une partie spécifique de la structure de données toujours/presque toujours/généralement nécessite une tenue de livre spécifique pour se produire. Dites lorsque vous mettez à jour la racine d'un arborescence, le cache de veille doit être purgé ou lorsque vous accédez à l'élément de données externe, un verrou doit être gagné/publié. Dans ces cas, il est logique d'appliquer le DRY directeur et colis ces actions ensemble.
Dans le contexte privé, il est toujours possible pour les autres fonctions de la famille à des étapes secondaires ces "getters et setters" et manipuler la structure de données. Par conséquent, pourquoi je pense à eux 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 droite.
Getters/Setters protégés
Dans un contexte protégé, ce n'est pas terriblement différent d'un contexte public. Les fonctions de rogue étranger éventuellement veulent avoir accès à la structure de données. Donc non, s'ils existent, ils fonctionnent comme des getteurs publics/setters.
À partir de l'expérience C++, le Setter/Getter est utile pour 2 scénarios:
De plus, la sécurité est un point valable, mais son importance est limitée à très peu d'applications de développement tels que la connexion ou les modules liés à l'accès à la DB. Pourquoi déranger un codage supplémentaire lorsque peu de personnes utilisent votre module?