J'ai cherché et je connais la différence théorique.
- public - Toute classe / fonction peut accéder à la méthode / propriété.
- protected - Seule cette classe et toutes les sous-classes peuvent accéder à la méthode / propriété.
- private - Seule cette classe peut accéder à la méthode / propriété. Il ne sera même pas hérité.
C'est très bien, la question est de savoir quelle est la différence pratique entre eux? Quand utiliseriez-vous private
et quand utiliseriez-vous protected
? Existe-t-il une bonne pratique standard ou acceptable par rapport à celle-ci?
Jusqu'à présent, pour conserver le concept d'héritage et de polymorphisme, j'utilise public
pour tout ce qui doit être accédé de l'extérieur (comme les constructeurs et les fonctionnalités de classe principale), et protected
pour les méthodes internes (logique, méthodes d'assistance, etc.). Suis-je sur la bonne voie?
(Notez que cette question est pour moi, mais aussi pour référence future car je n'ai pas vu de question comme celle-ci SO).
oop
language-agnostic
coding-style
Fantôme de Madara
la source
la source
internal
en langage C # qui limite le niveau d'accès d'une classe ou de ses membres au sein d'un assembly physique. Cependant, je ne suis pas sûr de son support ou de quelque chose de similaire dans d'autres langues.Réponses:
Non, vous n'êtes pas sur la bonne voie. Une bonne règle de base est la suivante: rendre tout aussi privé que possible. Cela rend votre classe plus encapsulée et permet de modifier les éléments internes de la classe sans affecter le code en utilisant votre classe.
Si vous concevez votre classe pour qu'elle soit héritable, choisissez avec soin ce qui peut être remplacé et accessible à partir des sous-classes, et rendez-le protégé (et finalement, en parlant de Java, si vous voulez le rendre accessible mais non remplaçable). Mais sachez que, dès que vous acceptez d'avoir des sous-classes de votre classe, et qu'il existe un champ ou une méthode protégé, ce champ ou cette méthode fait partie de l'API publique de la classe, et ne peut pas être modifié ultérieurement sans casser les sous-classes.
Une classe qui n'est pas destinée à être héritée doit être rendue définitive (en Java). Vous pouvez assouplir certaines règles d'accès (privé à protégé, final à non final) pour des raisons de test unitaire, mais ensuite les documenter et indiquer clairement que bien que la méthode soit protégée, elle n'est pas censée être remplacée.
la source
private
vsprotected
Quand est-ce que je veux qu'une propriété soit héritée, et quand n'est-ce pas? Je ne peux pas vraiment dire si un utilisateur veut parfois à l'avenir suivre mon cours et le prolonger ...Permettez-moi de commencer en disant que je parle ici principalement de l'accès aux méthodes et, dans une moindre mesure, du marquage des classes comme finales, et non de l' accès des membres.
La vieille sagesse
avait du sens à l'époque où il a été écrit, avant que l'open source ne domine l'espace des bibliothèques de développeurs et la gestion des VCS / dépendances. est devenu hyper collaboratif grâce à Github, Maven, etc. À l'époque, il y avait aussi de l'argent à gagner en limitant la ou les façons dont une bibliothèque pouvait être utilisée. J'ai passé probablement les 8 ou 9 premières années de ma carrière à adhérer strictement à cette «meilleure pratique».
Aujourd'hui, je pense que c'est un mauvais conseil. Parfois, il y a un argument raisonnable pour marquer une méthode comme privée ou une classe finale, mais c'est extrêmement rare, et même dans ce cas, cela n'améliore probablement rien.
As-tu déjà:
Voici les trois plus grandes rationalisations que j'ai entendues pour le marquage des méthodes privées par défaut:
Rationalisation n ° 1: ce n'est pas sûr et il n'y a aucune raison de remplacer une méthode spécifique
Je ne peux pas compter le nombre de fois où je me suis trompé sur la nécessité ou non de remplacer une méthode spécifique que j'ai écrite. Ayant travaillé sur plusieurs bibliothèques open source populaires, j'ai appris à mes dépens le coût réel du marquage des choses privées. Il élimine souvent la seule solution pratique aux problèmes imprévus ou aux cas d'utilisation. À l'inverse, je n'ai jamais, en plus de 16 ans de développement professionnel, regretté d'avoir marqué une méthode protégée au lieu de privée pour des raisons liées à la sécurité des API. Lorsqu'un développeur choisit d'étendre une classe et de remplacer une méthode, il dit consciemment «Je sais ce que je fais». et pour des raisons de productivité, cela devrait suffire. période. Si c'est dangereux, notez-le dans la classe / méthode Javadocs, ne vous contentez pas de claquer aveuglément la porte.
Les méthodes de marquage protégées par défaut sont une atténuation pour l'un des problèmes majeurs du développement de logiciels modernes: l'échec de l'imagination.
Rationalisation n ° 2: elle garde les API / Javadocs publiques propres
Celui-ci est plus raisonnable, et en fonction du public cible, cela peut même être la bonne chose à faire, mais cela vaut la peine de considérer le coût de maintien de l'API "propre": l'extensibilité. Pour les raisons mentionnées ci-dessus, il est probablement plus judicieux de marquer les éléments protégés par défaut au cas où.
Rationalisation n ° 3: Mon logiciel est commercial et je dois limiter son utilisation.
C'est également raisonnable, mais en tant que consommateur, j'irais avec le concurrent le moins restrictif (en supposant qu'il n'y ait pas de différences de qualité significatives) à chaque fois.
Ne jamais dire jamais
Je ne dis pas de ne jamais marquer les méthodes comme privées. Je dis que la meilleure règle de base est de "rendre les méthodes protégées à moins qu'il n'y ait une bonne raison de ne pas le faire".
Ce conseil est le mieux adapté pour ceux qui travaillent sur des bibliothèques ou des projets à plus grande échelle qui ont été divisés en modules. Pour les projets plus petits ou plus monolithiques, cela n'a pas autant d'importance car vous contrôlez tout le code de toute façon et il est facile de changer le niveau d'accès de votre code si / quand vous en avez besoin. Même dans ce cas, je donnerais toujours le même conseil :-)
la source
Rationalization # 1
- Lorsque je marque quelque chose comme protégé, je choisis de le faire explicitement car je pense que ce comportement n'est pas définitif et pourrait être un cas où mes classes enfants voudraient le remplacer. Si je ne suis pas si sûr, je voudrais le rendre privé par défaut. Surtout dans un langage comme C # qui conserve une méthode non virtuelle par défaut, l'ajout d'un spécificateur d'accès uniquement protégé n'a aucun sens. Vous devez ajouter à la fois des motsvirtual
-protected
clés et pour rendre votre intention très claire. De plus, les gens préfèrent l'association à l'héritage, de sorteprotected
que la valeur par défaut est difficile à percevoirArrêtez d'abuser des champs privés !!!
Les commentaires ici semblent être extrêmement favorables à l'utilisation de champs privés. Eh bien, j'ai quelque chose de différent à dire.
Les champs privés sont-ils bons en principe? Oui. Mais dire qu'une règle d'or est de rendre tout privé lorsque vous n'êtes pas sûr que ce soit vraiment faux ! Vous ne verrez pas le problème jusqu'à ce que vous en rencontriez un. À mon avis, vous devriez marquer les champs comme protégés si vous n'êtes pas sûr .
Il existe deux cas pour lesquels vous souhaitez étendre une classe:
Il n'y a rien de mal avec les champs privés dans le premier cas. Le fait que les gens abusent des champs privés rend très frustrant lorsque vous découvrez que vous ne pouvez pas modifier la merde.
Considérez une bibliothèque simple qui modélise des voitures:
L'auteur de la bibliothèque a pensé: il n'y a aucune raison pour laquelle les utilisateurs de ma bibliothèque ont besoin d'accéder aux détails d'implémentation de
assembleCar()
droite? Marquons la vis comme privée.Eh bien, l'auteur a tort. Si vous souhaitez modifier uniquement la
assembleCar()
méthode sans copier toute la classe dans votre package, vous n'avez pas de chance. Vous devez réécrire votre proprescrew
champ. Disons que cette voiture utilise une douzaine de vis, et chacune d'elles implique un code d'initialisation non trivial dans différentes méthodes privées, et ces vis sont toutes marquées comme privées. À ce stade, ça commence à sucer.Oui, vous pouvez dire avec moi que l'auteur de la bibliothèque aurait pu écrire un meilleur code donc il n'y a rien de mal avec les champs privés . Je ne dis pas que le champ privé est un problème avec la POO . C'est un problème lorsque les gens les utilisent.
La morale de l'histoire est que si vous écrivez une bibliothèque, vous ne savez jamais si vos utilisateurs veulent accéder à un domaine particulier. Si vous n'êtes pas sûr, marquez-le
protected
pour que tout le monde soit plus heureux plus tard. Au moins, n'abusez pas du domaine privé .Je soutiens beaucoup la réponse de Nick.
la source
Il y a quelque temps, j'ai lu un article qui parlait de verrouiller au maximum chaque classe. Rendez tout final et privé, sauf si vous avez un besoin immédiat d'exposer certaines données ou fonctionnalités au monde extérieur. Il est toujours facile d'étendre la portée pour qu'elle soit plus autorisée plus tard, mais pas l'inverse. Tout d' abord envisager de faire autant de choses que possible
final
qui fera le choix entreprivate
etprotected
beaucoup plus facile.Maintenant, s'il vous reste une classe finale, rendez tout privé à moins que le monde n'en ait absolument besoin - rendez-le public.
S'il vous reste une classe qui a des sous-classes, examinez attentivement chaque propriété et méthode. Considérez d'abord si vous souhaitez même exposer cette propriété / méthode à des sous-classes. Si vous le faites, déterminez si une sous-classe peut faire des ravages sur votre objet si elle a gâché la valeur de la propriété ou l'implémentation de la méthode lors du processus de substitution. Si c'est possible, et que vous voulez protéger la propriété / méthode de votre classe même des sous-classes (cela semble ironique, je sais), alors rendez-la privée. Sinon, protégez-le.
Avertissement: je ne programme pas beaucoup en Java :)
la source
final class
en Java est une classe dont on ne peut pas hériter. Afinal method
n'est pas virtuel, c'est-à-dire qu'il ne peut pas être remplacé par une sous-classe (les méthodes Java sont virtuelles par défaut). Afinal field/parameter/variable
est une référence de variable immuable (dans le sens où elle ne peut pas être modifiée après avoir été initialisée).Quand utiliseriez-vous
private
et quand utiliseriez-vousprotected
?L'héritage privé peut être considéré comme mis en œuvre en termes de relation plutôt que de relation IS-A . En termes simples, l'interface externe de la classe héritière n'a aucune relation (visible) avec la classe héritée. Elle n'utilise l'
private
héritage que pour implémenter une fonctionnalité similaire fournie par la classe Base.Contrairement à l'héritage privé, l' héritage protégé est une forme restreinte d'héritage, dans laquelle la classe dérivée IS-A est une sorte de classe de base et souhaite restreindre l'accès des membres dérivés uniquement à la classe dérivée.
la source
Eh bien, tout est question d'encapsulation si les classes de factures de paiement gèrent la facturation du paiement, puis dans la classe de produit, pourquoi aurait-il besoin de tout le processus de facturation, c'est-à-dire du mode de paiement comment payer où payer ... donc ne laisser que ce qui est utilisé pour d'autres classes et objets rien de plus que ce public pour ceux que d'autres classes utiliseraient aussi, protégé pour ces limites uniquement pour l'extension des classes. Comme vous êtes madara uchiha, le privé est comme
"limboo"
vous pouvez le voir (vous ne classez qu'une seule classe).la source