De nombreuses réponses ont déjà été ajoutées à ce fil de discussion intéressant, mais je n'ai pas trouvé la véritable raison pour laquelle il est nécessaire d'agir. pourquoi ce comportement est ce qu'il est. Laissez-moi faire un essai :
A l'époque
Quelque part entre Smalltalk dans les années 80 et Java au milieu des années 90, le concept d'orientation objet a mûri. Le masquage de l'information, qui n'était pas considéré à l'origine comme un concept propre à l'OO (mentionné pour la première fois en 1978), a été introduit dans Smalltalk : toutes les données (champs) d'une classe sont privées, toutes les méthodes sont publiques. Au cours des nombreux développements de l'OO dans les années 90, Bertrand Meyer a tenté de formaliser la plupart des concepts de l'OO dans son ouvrage de référence, intitulé Construction de logiciels orientés objet (OOSC) qui est depuis lors considéré comme une référence (presque) définitive sur les concepts OO et la conception des langages.
Dans le cas de la visibilité privée
Selon Meyer, une méthode doit être mise à la disposition d'un ensemble défini de classes (page 192-193). Cela donne évidemment une granularité très élevée de masquage de l'information, la fonction suivante est disponible pour les classesA etB et tous leurs descendants :
feature {classA, classB}
methodName
Dans le cas de private
il dit ceci : sans déclarer explicitement qu'un type est visible par sa propre classe, vous ne pouvez pas accéder à cette fonctionnalité (méthode/champ) dans un appel qualifié. C'est-à-dire que si x
est une variable, x.doSomething()
n'est pas autorisé. L'accès non qualifié est autorisé, bien sûr, à l'intérieur de la classe elle-même.
En d'autres termes, pour autoriser l'accès à une instance de la même classe, vous devez autoriser explicitement l'accès à la méthode par cette classe. C'est ce qu'on appelle parfois "instance-privée" ou "classe-privée".
Instance-privée dans les langages de programmation
Je connais au moins deux langages actuellement utilisés qui utilisent le masquage d'informations privé par instance par opposition au masquage d'informations privé par classe. L'un est Eiffel, un langage conçu par Meyer, qui pousse l'OO à l'extrême. L'autre est Ruby, un langage beaucoup plus courant de nos jours. En Ruby, private
signifie : "privé à cette instance" .
Choix pour la conception de la langue
Il a été suggéré que l'autorisation de l'instance-private serait difficile pour le compilateur. Je ne le pense pas, car il est relativement simple d'autoriser ou d'interdire les appels qualifiés aux méthodes. Si pour une méthode privée, doSomething()
est autorisé et x.doSomething()
ne l'est pas, le concepteur du langage a effectivement défini l'accessibilité par instance uniquement pour les méthodes et les champs privés.
D'un point de vue technique, il n'y a pas de raison de choisir une voie ou l'autre (surtout si l'on considère que Eiffel.NET peut faire cela avec IL, même avec l'héritage multiple, il n'y a pas de raison inhérente de ne pas fournir cette fonctionnalité).
Bien sûr, c'est une question de goût et comme d'autres l'ont déjà mentionné, certaines méthodes pourraient être plus difficiles à écrire sans la fonctionnalité de visibilité des méthodes et champs privés au niveau de la classe.
Pourquoi C# n'autorise que l'encapsulation de classe et non l'encapsulation d'instance ?
Si vous regardez les fils de discussion sur Internet concernant l'encapsulation d'instance (un terme parfois utilisé pour faire référence au fait qu'un langage définit les modificateurs d'accès au niveau de l'instance, par opposition au niveau de la classe), le concept est souvent désapprouvé. Cependant, si l'on considère que certains langages modernes utilisent l'encapsulation d'instance, au moins pour le modificateur d'accès privé, on peut penser qu'il peut être et est utile dans le monde de la programmation moderne.
Cependant, il faut reconnaître que C# a regardé de plus près C++ et Java pour la conception de son langage. Eiffel et Modula-3 étaient également dans le coup, mais compte tenu des nombreuses caractéristiques manquantes d'Eiffel (héritage multiple), je pense qu'ils ont choisi la même voie que Java et C++ en ce qui concerne le modificateur d'accès privé.
Si vous voulez vraiment connaître le pourquoi vous devriez essayer de mettre la main sur Eric Lippert, Krzysztof Cwalina, Anders Hejlsberg ou toute autre personne ayant travaillé sur le standard de C#. Malheureusement, je n'ai pas pu trouver de note définitive dans la version annotée de la norme C#. Le langage de programmation C# .
18 votes
Quels sont les avantages de l'alternative ?
19 votes
Il est vrai qu'il ne modélise pas très bien le monde réel. Après tout, ce n'est pas parce que ma voiture peut indiquer combien d'essence il lui reste que ma voiture devrait être capable de dire combien d'essence il reste à TOUTES les voitures. Donc, oui, je peux théoriquement envisager d'avoir un accès "instance privée". J'ai l'impression que je ne l'utiliserais jamais parce que je craindrais que dans 99% des cas, je voudrais vraiment qu'une autre instance accède à cette variable.
2 votes
La position qui a été adoptée pour les soi-disant "avantages" est que les classes ne devraient pas connaître l'état interne d'une autre instance - indépendamment du fait qu'il s'agit du même type. Ce n'est pas un avantage en soi, mais il y a probablement une bonne raison de choisir l'une plutôt que l'autre et c'est ce que nous avons essayé de déterminer.
5 votes
Vous pouvez toujours transformer la variable en une paire de fermetures getter/setter, initialisées dans le constructeur, qui échoueront si este n'est pas le même que lors de l'initialisation ...
0 votes
Je suis presque sûr qu'une question sur les instances-locales a déjà été posée, mais je ne la trouve pas. Celle-ci est cependant liée : programmateurs.stackexchange.com/questions/82047/
9 votes
Scala fournit instance privée ainsi que de nombreux autres niveaux d'accès que l'on ne trouve pas dans Java, C# et de nombreux autres langages. C'est une question parfaitement légitime.
0 votes
@RichK : La question est de savoir si un objet doit savoir qu'un autre objet est "réellement" du même type. Si
Foo
accèdent aux éléments internes d'autresFoo
alors tout objet substituable à l'objetFoo
doit avoir les mêmes internes. En revanche, si unFoo
n'accède jamais aux données internes d'un autre objetFoo
on pourrait diviserFoo
en une classe de base abstraite (qui est utilisée pour tout sauf pour les appels de constructeurs qui sont faits par une usine dans cette classe), et un type d'instance concret, et les implémentations de la classe de base pourraient avoir les internes qu'elles veulent.1 votes
Je pense que ce que @JonSkeet veut dire, c'est que les modificateurs d'accès ont à voir avec
Public API
d'une classe. Puisque j'ai écrit MA classe, je sais à tout moment qu'elle doit pouvoir accéder à d'autres instances. Le fait que ma classe puisse voir les membres privés d'autres instances n'est pas pertinent pour l'API publique. Si vous voulez que vos membres privés soient invisibles aux autres instances de la classe, c'est facile, très facile. Il suffit de ne pas le faire dans la classe.0 votes
Voir aussi Pourquoi et comment C# permet-il d'accéder à des variables privées en dehors de la classe elle-même lorsqu'elle se trouve dans la même classe contenante ? ... et en plus Pourquoi une variable membre privée peut-elle être modifiée par une instance de classe ?