l’utilisation de mot-clé privé

Je suis nouveau en programmation. J’apprends Java maintenant, il y a quelque chose que je ne suis pas vraiment sûr, c’est l’utilisation de privé. Pourquoi le programmeur a-t-il défini la variable comme privée, puis écrit, getter et configurateur pour y accéder. Pourquoi ne pas tout mettre en public puisque nous l’utilisons quand même.

public class BadOO { public int size; public int weight; ... } public class ExploitBadOO { public static void main (Ssortingng [] args) { BadOO b = new BadOO(); b.size = -5; // Legal but bad!! } } 

J’ai trouvé du code comme celui-ci, et j’ai vu le commentaire légal mais mauvais. Je ne comprends pas pourquoi, expliquez-moi s’il vous plaît.

La principale raison de ne pas simplement rendre la variable publique en premier lieu est que si vous la rendiez publique, vous créeriez plus de maux de tête plus tard.

Par exemple, un programmeur écrit des getters et des setters publics autour d’une variable de membre privé. Trois mois plus tard, il doit vérifier que la variable n’est jamais “définie” à null. Il ajoute une vérification dans la méthode “setFoo (…)”, et toutes les tentatives pour définir la variable seront alors vérifiées pour “la mettre à null”. Cas fermé, et avec peu d’effort.

Un autre programmeur se rend compte que mettre des getters et des setters publics autour d’une variable membre privé viole l’esprit d’encapsulation, il voit la futilité des méthodes et décide de rendre le membre variable public. Peut-être cela augmente-t-il un peu la performance, ou peut-être le programmeur veut-il simplement “l’écrire comme il est utilisé”. Trois mois plus tard, il doit vérifier que la variable n’est jamais “définie” à null. Il parsing chaque access à la variable, en parcourant efficacement la totalité de la base de code, y compris tous les codes pouvant accéder à la variable via la reflection. Cela inclut toutes les bibliothèques tierces qui ont étendu son code et tous les modules nouvellement écrits qui ont utilisé son code après sa rédaction. Il modifie ensuite tous les appels pour garantir que la variable n’est jamais définie sur null. Le dossier n’est jamais fermé, car il ne peut pas trouver tous les access au membre exposé, ni accéder à tous les codes sources tiers. Avec une connaissance imparfaite des modules nouvellement rédigés, l’enquête est incomplète. Enfin, il n’a aucun contrôle sur le futur code pouvant accéder au membre public, et ce code peut contenir des lignes qui définissent la variable membre sur null.

Bien sûr, le deuxième programmeur pourrait alors briser tout le code existant en plaçant “get” et “set” des méthodes autour de la variable et en le rendant privé, mais bon, il aurait pu le faire trois mois plus tôt et casser le code de tout le monde.

Appelez ça comme vous voulez, mais placer des méthodes publiques de «get» et de «set» autour d’une variable membre privé est une programmation défensive qui a été mise en place pendant de nombreuses années (plusieurs décennies) d’expérience.

La raison la plus importante est de masquer les détails d’implémentation internes de votre classe. Si vous empêchez les programmeurs de s’appuyer sur ces détails, vous pouvez modifier en toute sécurité l’implémentation sans vous soucier de casser le code existant qui utilise la classe.

Ainsi, en déclarant le champ privé, vous empêchez un utilisateur d’accéder directement à la variable. En fournissant des objects et des règles, vous contrôlez exactement comment un utilisateur peut contrôler la variable.

Tout ce qui est public dans votre classe est un contrat avec les utilisateurs de la classe. Lorsque vous modifiez la classe, vous devez maintenir le contrat. Vous pouvez append au contrat (nouvelles méthodes, variables, etc.), mais vous ne pouvez pas le supprimer. Idéalement, vous voulez que ce contrat soit aussi petit que possible. Il est utile de rendre privé tout ce que vous pouvez. Si vous avez besoin d’un access direct aux membres du package, protégez-le. Ne publiez que les éléments requirejs par vos utilisateurs.

Exposer des variables signifie que vous contractez pour toujours, avoir cette variable et permettre aux utilisateurs de la modifier. Comme discuté ci-dessus, vous pouvez trouver que vous devez appeler le comportement quand une variable est accédée. Cela peut être fait si vous ne contractez que pour les méthodes getter et setter.

La plupart des anciennes classes Java ont des contrats qui exigent qu’elles soient thread-safe. Cela ajoute une surcharge importante dans les cas où un seul thread peut accéder à l’instance. Les nouvelles versions ont de nouvelles classes qui dupliquent ou améliorent les fonctionnalités mais suppriment la synchronisation. Ainsi, SsortingngBuilder a été ajouté et dans la plupart des cas, devrait être utilisé à la place de SsortingngBuffer.

C’est considéré comme mauvais principalement parce que vous perdez le contrôle sur qui peut changer la valeur et ce qui se passe quand la valeur change.

Dans une application minuscule écrite par vous pour vous, cela ne semble pas important, mais lorsque vous commencez à développer pour des applications plus grandes et plus grandes qui contrôlent qui change quoi et quand, cela devient critique.

Imaginez-vous d’après votre exemple ci-dessus, vous publiez la bibliothèque telle quelle, d’autres personnes l’utilisent, puis vous décidez de calculer une autre valeur dans votre mauvaise classe lorsque la taille change … soudain, la classe bad00 n’a aucun moyen de savoir t pas le changer parce que d’autres personnes en dépendent.

Au lieu de cela, si vous aviez une méthode définie, vous pouvez l’étendre pour dire

 void SetSize(int newSize) { size = newSize; DoCalculation; } 

Vous pouvez étendre la fonctionnalité sans empêcher les autres de compter sur vous.

Je recommande fortement le livre Effective Java , il contient beaucoup d’informations utiles sur la façon d’écrire de meilleurs programmes en Java.

Votre question est traitée aux points 13 et 14 de ce livre:

  • Point 13: minimiser l’accessibilité des classes et des membres
  • Elément 14: Dans les classes publiques, utilisez des méthodes d’access, pas des champs publics

Vous ne devez pas autoriser les implémentations à modifier directement vos enregistrements. Fournir des getters et des setters signifie que vous avez un contrôle exact sur l’atsortingbution des variables ou sur ce qui est retourné, etc. La même chose vaut pour le code de votre constructeur. Que se passe-t-il si le configurateur fait quelque chose de spécial lorsque vous atsortingbuez une valeur à la taille? Cela n’arrivera pas si vous l’assignez directement.

Il s’agit d’un comportement courant de nombreux programmeurs – du code Java avec private champs private et public accesseurs et des mutateurs public . L’effet est comme vous le dites, ces champs pourraient aussi bien avoir été public .

Il existe des langages de programmation qui traitent également de l’autre extrême. Regardez Python. à peu près tout est public, dans une certaine mesure.

Ce sont des pratiques de codage différentes et une chose courante avec laquelle les programmeurs traitent chaque jour. Mais en Java, voici ma règle de base:

  • Si le champ est utilisé uniquement comme atsortingbut, lisible et accessible en écriture par quiconque, rendez-le public .
  • Si le champ est utilisé en interne uniquement, utilisez private . Fournissez un getter si vous voulez un access en lecture et fournissez un setter si vous voulez un access en écriture.
  • Il y a un cas particulier: parfois, vous souhaitez traiter des données supplémentaires lors de l’access à un atsortingbut. Dans ce cas, vous fourniriez à la fois les getters et les setters, mais dans ces fonctions de propriété, vous feriez plus que simplement return – par exemple, si vous souhaitez suivre le nombre de fois qu’un atsortingbut est lu par d’autres programmes .

Ce n’est qu’un bref aperçu des niveaux d’access. Si cela vous intéresse, consultez également l’access protected .

Ceci est en effet utilisé pour masquer l’implémentation interne. Cela aide également à fournir un peu de logique supplémentaire sur vos variables. Disons que vous devez vous assurer que la valeur transmise pour une variable ne doit pas être 0 / null, vous pouvez fournir cette logique dans la méthode set. De la même manière, vous pouvez fournir une certaine logique tout en obtenant la valeur, disons que vous avez une variable object qui n’est pas initialisée et que vous accédez à cet object. Dans ce cas, vous fournissez la logique pour vérifier cet object et renvoyer toujours un object.

Les programmeurs C # l’utilisent autant, ou peut-être plus fréquemment que ce que je vois en Java. C # appelle cela propriétés où en Java il s’agit d’accesseurs / mutateurs

Pour moi, il est logique d’avoir des méthodes getter et setter pour encapsuler les classes afin qu’aucune classe ne puisse modifier les variables d’instance d’une autre classe.

D’accord. Nous parlons d’objects ici. Les objects du monde réel. S’ils ne sont pas privés, l’utilisateur de votre classe est autorisé à changer. Et si, pour une classe Circle et pour l’atsortingbut / propriété radius de la classe Circle, l’utilisateur définit la valeur comme «0». Cela n’a pas de sens pour un cercle d’exister avec un rayon égal à «0». Vous pouvez éviter de telles erreurs si vous rendez vos atsortingbuts privés et indiquez une méthode setter et dans laquelle et lancez une exception / erreur (indiquant à l’utilisateur) qu’il n’est pas autorisé de créer un cercle avec radisu comme ‘0’. Fondamentalement, les objects créés en dehors de votre classe sont censés exister comme vous le souhaitiez. C’est l’un des moyens d’y parvenir.

Comme indiqué précédemment, la création d’une variable privée a pour but de la masquer de l’extérieur. Mais si vous créez un getter ET un setter, vous pouvez aussi rendre la variable publique. Si vous vous trouvez plus tard dans une position où vous avez fait le mauvais choix, vous devez modifier votre code en utilisant la variable publique en utilisant le getter / setter, ce qui peut ne pas être un problème. Mais cela peut poser problème si un autre code, que vous ne contrôlez pas, commence en fonction de votre code. Ensuite, une telle refactorisation cassera l’autre code. Si vous utilisez des getter et des setters dès le début, vous réduirez ce risque en échange d’un petit effort. Cela dépend donc de votre situation.

Cela dépend de qui accède à ces variables publiques. Très probablement, uniquement par des personnes au sein de votre entreprise / équipe. Ensuite, il est sortingvial de les reformuler dans des accesseurs / régleurs lorsque cela est nécessaire. Je dis que dans ce cas, il vaut mieux laisser les variables publiques; sauf si vous êtes obligé de suivre la convention java bean.

Si vous écrivez un framework ou une bibliothèque destinée au public, vous ne devez pas exposer de variables. Il est impossible pour vous de les changer plus tard en accesseurs.

Mais le 2ème cas est plus rare que le premier; les gens appliquent des hypothèses extrêmement déraisonnables en ce qui concerne l’ingénieur logiciel, comme s’ils n’écrivaient pas de code, au lieu de cela ils gravaient du code dans la pierre. Et comme si le monde entier regardait pendant que vous codiez, en réalité, personne ne lira jamais votre code sauf vous-même.