Dois-je utiliser publiques ou privées de variables?
Je suis en train de réaliser un grand projet pour la première fois. J'ai beaucoup de classes et certains d'entre eux ont des variables publiques, certains ont des variables privées avec setter et getter méthodes et même avoir les deux types.
J'ai décidé de réécrire ce code à utiliser principalement d'un seul type. Mais je ne sais pas qui je dois utiliser la (les variables qui sont utilisées que pour les méthodes dans le même objet sont toujours privées et ne sont pas l'objet de cette question).
Je sais que la théorie quels moyens publics et privés nécessaires, mais ce qui est utilisé dans le monde réel, et pourquoi?
- Le OO réponse serait d'utiliser des variables privées. Mais le modèle de la visibilité en C++ est tout à fait rompu (un peu moins le cas en C++11) et les membres privés peuvent provoquer de très surprenant si vous ne leur donnez pas uglified noms.
- Wut?
- Près d'une exacte dupe: stackoverflow.com/questions/1596432/...
- Avant C++11, ayant une surcharge à l'aide de T::x dans sa signature serait la cause d'une erreur de disque dur si vous avez appelé une autre surcharge sur un type avec un privé x membre. Mais même en C++11, vous obtenez toujours des questions comme: gcc.gnu.org/bugzilla/show_bug.cgi?id=55713 où, au lieu d'ignorer les membres privés (ou bases), le compilateur insiste sur le fait de donner une erreur. Il y a certainement pire. Plusieurs membres du comité ont entendu l'appel de la C++ de contrôle d'accès cassé mais je pense qu'il l'a été pour des raisons différentes.
Vous devez vous connecter pour publier un commentaire.
private
données membres sont généralement considérée comme bonne, car ils fournissent de l'encapsulation.Fournir des getters et setters pour eux pauses que l'encapsulation, mais c'est toujours mieux que
public
de données de membres, car il n'y a qu'une fois le point d'accès à ces données.Vous pourrez le constater au cours de débogage. Si c'est privé, vous savoir vous pouvez uniquement modifier la variable à l'intérieur de la classe. Si elle est publique, vous aurez à chercher l'ensemble de la base de code de l'endroit où il pourrait être modifié.
Autant que possible, l'interdiction des getters/setters et de faire propriétés
private
. Il suit le principe de se cacher de l'information - vous ne devriez pas vous soucier de ce que les propriétés d'une classe a. Il doit être autonome. Bien sûr, dans la pratique, ce n'est pas faisable, et si elle l'est, un design qui suit, il sera plus encombrée et plus difficile à maintenir que celui qui ne l'est pas.Bien sûr, ceci est une règle de base - par exemple, je veux juste utiliser un
struct
(l'équivalent d'unclass
avec accès public) pour, disons, une simple classe point:private
membres avecpublic
setters doit être préférée à lapublic
membres, parce que c'est la seule façon que vous avez de contrôle sur la façon dont le membre est changé. Cela peut (par exemple) être utile pour soutenir la hausse de compatibilité. Imaginez qu'une nouvelle version de votre Point2D seulement de gérer des valeurs entre -100.0 et +100.0. Il n'y a pas de (simple) de façon à mettre en œuvre des ce avec la structure ci-dessus sans qu'il en résulte une modification du code de la clientèle à l'aide de cette structure.Point2D
plus, est-il. C'est unRestrictedPoint2D
. 🙂Point2D
qui seraient alors tenter de changer l'interface d'Point2D
. Vous ne savez jamais combien de vos classes vont être utilisés dans la nature, en utilisant des getters/setters fournit un moyen de mettre en œuvre de nouvelles fonctionnalités sans rupture de l'interface.Puisque vous dites que vous connaissez la théorie, et les autres réponses ont creusé dans le sens de public/privé, des getters et setters, j'aimerais me concentrer sur le pourquoi de l'utilisation des accesseurs au lieu de créer publique attributs (membre de données en C++).
Imaginez que vous avez une classe de Camion dans la logistique du projet:
À condition que vous êtes etats-unis, vous aurez probablement utiliser gallons afin de représenter la capacité de vos camions. Imaginez que votre projet est terminé, il fonctionne parfaitement, bien que de nombreuses utilisations directes de
Truck::capacity
sont fait. En fait, votre projet devient un succès, de sorte que certaines entreprise européenne vous demande d'adapter votre projet à eux; malheureusement, le projet doit utiliser le système métrique maintenant, donc litres au lieu de gallons devrait être utilisé pour la capacité.Maintenant, ce pourrait être un gâchis. Bien sûr, une possibilité pourrait être de préparer une base de code seulement pour l'Amérique du Nord, et une base de code seulement pour l'Europe. Mais cela signifie que des corrections de bug doit être appliqué en deux différentes sources de code, et qu'il est décidé à être irréalisable.
La solution est de créer une configuration possible dans votre projet. L'utilisateur doit être capable de mettre en gallons ou en litres, au lieu de l'être fixe filaire choix de gallons.
Avec l'approche vu ci-dessus, cela signifie beaucoup de travail, vous devrez traquer toutes les utilisations de
Truck::capacity
, et de décider quoi faire avec eux. Cela signifie probablement de modifier les fichiers sur l'ensemble de la base de code. Supposons, à titre d'alternative, que vous avez décidé d'un plustheoretic
approche.Une possible alternative changement n'implique pas de modification de l'interface de la classe:
(Veuillez prendre int compte qu'il y a beaucoup de façons pour ce faire, que l'on n'est qu'une possibilité, et ce n'est qu'un exemple)
Vous devrez créer le mondial de l'utilitaire de configuration classe (mais vous avez eu à faire de toute façon), et ajouter un include dans
truck.h
pourconfiguration.h
, mais ce sont toutes les modifications locales, le reste de votre base de code reste inchangé, évitant ainsi d'éventuels bugs.Enfin, vous déclarez également que vous travaillez maintenant dans un grand projet, qui, je pense, c'est le genre de domaine où ces raisons en fait plus de sens. Rappelez-vous que l'objectif de garder à l'esprit tout en travaillant dans de grands projets est de créer maintenable code, c'est à dire, le code qui vous permet de corriger et de s'étendre avec de nouvelles fonctionnalités. Vous pouvez oublier les getters et les setters personnels, des petits projets, bien que j'avais essayer de le faire moi-même utilisé pour eux.
Espère que cette aide.
Il n'y a pas de règle quant à ce qui devrait être privé/public ou protégé.
Il dépend sur le rôle de votre classe et ce qu'il offre.
la classe doit être faite privé.
pourrait être déclaré comme protégé.
De la programmation orientée objet à partir d'un point de vue des getters/setters aider avec l'encapsulation et devrait donc toujours être utilisé. Lorsque vous appelez un getter/setter de la classe peut faire ce qu'il veut derrière les coulisses et le fonctionnement interne de la classe ne sont pas exposées à l'extérieur.
D'autre part, à partir d'un C++ point de vue, il peut aussi être un inconvénient, si la classe ne comprend beaucoup de choses inattendues quand vous voulez juste pour obtenir/définir une valeur. Les gens aiment savoir si certains d'accéder à des résultats en surcharge énorme ou il est simple et efficace. Lorsque vous accédez à une variable publique vous savez exactement ce que vous obtenez lorsque vous utilisez un getter/setter vous n'avez aucune idée.
Surtout si vous ne faites qu'un petit projet, de dépenser votre temps à écrire des getters/setters et le réglage de toutes lorsque vous décidez de changer votre nom de variable/type de/... produit beaucoup de travail pour peu de gain. Vous feriez mieux de passer du temps à écrire du code qui fait quelque chose d'utile.
C++ en général, le code ne pas utiliser des getters/setters quand ils ne fournissent pas de réel gain. Si vous concevez un de 1 000 000 de projet en ligne, avec beaucoup de modules qui doivent être aussi indépendants que possible, il peut avoir du sens, mais pour la plupart de taille normale code que vous écrivez au jour le jour, ils sont beaucoup trop lourds.
Il y a certains types de données, dont le seul but est de maintenir le bien-données spécifié. Ceux-ci peuvent généralement être écrit avec les structures de données publiques des membres. A côté de cela, une classe doit définir une abstraction. Les variables publiques ou trivial setters et getters suggère que la conception n'a pas été pensé suffisamment, ce qui résulte dans une agglomération de la faiblesse des abstractions qui n'est pas abstrait, beaucoup de n'importe quoi. Au lieu de penser à des données, pensez à comportement: cette classe doit faire X, Y et Z. a Partir de là, décider quelles données interne est nécessaire pour supporter le comportement souhaité. Ce n'est pas facile au premier abord, mais rappelez-vous que c'est un comportement qui importe, pas les données.
Privé variables membres sont privilégiées sur les variables de membre publiques, principalement pour les raisons indiquées ci-dessus (l'encapsulation, bien spécifiée des données, etc..). Ils fournissent également une protection des données en tant que bien, car il garantit qu'aucune entité extérieure peut modifier la variable de membre sans passer par le bon canal d'un poseur en cas de besoin.
Un autre avantage de getters et setters, c'est que si vous utilisez un IDE comme Eclipse ou Netbeans), vous pouvez utiliser l'IDE de la fonctionnalité de recherche pour chaque endroit dans le code où la fonction est appelée. Ils offrent une visibilité quant à l'endroit où un élément de données dans la classe supérieure est en train d'être utilisé ou modifié. Aussi, vous pouvez facilement faire de l'accès aux variables membres thread-safe par la présence d'un interne de mutex. Les getter/setter fonctions de saisir ce mutex avant d'accéder ou de modifier la variable.
Je suis un partisan de l'abstraction, au point où il est encore utile. L'Abstraction pour le bien de l'abstraction se traduit généralement par une encombré désordre qui est plus compliqué que sa en vaut la peine.
Variables publiques sont généralement découragés, et la meilleure forme est de faire de toutes les variables privées et d'y accéder avec des getters et setters:
Moderne Ide comme Eclipse et d'autres aident à vous en proposant des fonctionnalités comme "mettre en Œuvre des Getters et Setters" et "Encapsuler Terrain" (qui remplace tous les directs acccesses de variables avec le getter et setter appels).