Existe-il des règles claires sur l'utilisation de chacune de ces lors de la prise de classes et d'interfaces et de traiter avec l'héritage?
Réponses
Trop de publicités?Ce Java tutoriel peut être de quelque utilité pour vous.
Modificateur | Classe | Package | Sous-Classe | Monde ------------+-------+---------+----------+------- public | y | y | y | y ------------+-------+---------+----------+------- protégé | y | y | y | n ------------+-------+---------+----------+------- aucun modificateur | y | y | n | n ------------+-------+---------+----------+------- privé | y | n | n | n y: accessible n: non accessible
(Avertissement: je ne suis pas un programmeur Java, je suis un programmeur de Perl. Perl a pas de protections qui est peut-être pourquoi je comprends le problème :) )
Privé
Comme vous le croyez, seule la classe dans laquelle elle est déclarée à la voir.
Colis Privé
Ne peut être vu et utilisé par le paquet dans lequel elle a été déclarée. C'est la valeur par défaut en Java (que certains considèrent comme une erreur).
Protégé
Colis Privé + peut être vu par les sous-classes ou package membre.
Public
Tout le monde peut le voir.
Publié
Visible à l'extérieur le code que j'ai le contrôle. (Bien que pas la syntaxe Java, il est important que cette discussion).
C++ définit un niveau supplémentaire appelé "ami" et le moins vous connaissez le mieux.
Quand devez-vous utiliser quoi? L'idée est d'encapsulation de cacher des informations. Autant que possible, vous souhaitez masquer le détail de la façon dont quelque chose est fait à partir de vos utilisateurs. Pourquoi? Parce qu'alors vous pouvez les modifier par la suite et pour ne pas casser le code de personne. Cela vous permet d'optimiser, de refactoriser, la révision et la correction de bugs, sans s'inquiéter que quelqu'un était à l'aide de ce code que vous venez d'une refonte.
Donc, la règle de base est de faire les choses uniquement visible comme ils doivent l'être. Démarrer avec le privé, et ne fait qu'ajouter plus de visibilité en tant que de besoin. Seulement de rendre public ce qui est absolument nécessaire pour l'utilisateur de connaître, chaque détail vous rendre publics les crampes de votre capacité à la refonte du système.
Si vous souhaitez que les utilisateurs soient en mesure de personnaliser les comportements, plutôt que de faire des internes au public afin qu'ils puissent les remplacer, il est souvent une meilleure idée de la pousser ces tripes dans un objet et de faire l'interface publique. De cette façon, ils peuvent tout simplement brancher un nouvel objet. Par exemple, si vous écriviez un lecteur de CD et voulait "aller trouver des infos sur ce CD" peu personnalisable, plutôt que de rendre ces méthodes public vous avait mis tout ce que la fonctionnalité dans son propre objet et l'objet de votre getter/setter public. Dans cette façon d'être avares exposer vos tripes encourage une bonne composition et de la séparation des préoccupations
Personnellement, j'en tenir à "privé" et "public". De nombreux langages à objets juste que. "Protégés" peut être pratique, mais c'est vraiment de la triche. Une fois que l'interface est plus que privé, il est hors de votre contrôle et vous devez aller à la recherche d'autres personnes, du code d'usages.
C'est là que l'idée de "publié". Modification de l'interface (refactoring) exige que vous trouverez tout le code qui l'utilise et de changement que, trop. Si l'interface est privé, et bien pas de problème. Si elle est protégée, vous devez aller trouver tous les sous-classes. Si elle est publique, vous devez aller trouver tout le code qui utilise votre code. Parfois, cela est possible, par exemple si vous travaillez sur l'entreprise code pour usage interne seulement il n'a pas d'importance si une interface est public. Vous pouvez saisir tout le code du référentiel de l'organisation. Mais si une interface est "publié", si il y a du code à l'aide en dehors de votre contrôle, vous êtes arrosé. Vous devez prendre en charge l'interface ou le risque de casser le code. Même les interfaces protégées peut être considéré comme publié (c'est pourquoi je ne vous embêtez pas avec une protection).
De nombreux langages de trouver la nature hiérarchique de la public/protected/private trop restrictif et ne sont pas conformes à la réalité. À cette fin, il est le concept d'un trait de classe, mais c'est un autre spectacle.
| highest precedence <---------> lowest precedence
*---------------+----------------+-----------+---------------+-------
\ xCanBeSeenBy | this | any class | this subclass | any
\ | class | in same | in another | class
\---------\ | nonsubbed | package | package |
Modifier of x \ | | | |
----------------*----------------+-----------+---------------+-------
public | ✔ | ✔ | ✔ | ✔
----------------+----------------+-----------+---------------+-------
protected | ✔ | ✔ | ✔ | ✘
----------------+----------------+-----------+---------------+-------
package-private | | | |
(no modifier) | ✔ | ✔ | ✘ | ✘
----------------+----------------+-----------+---------------+-------
private | ✔ | ✘ | ✘ | ✘
Règle simple. Début de déclarer tout privé. Et puis les progrès sur la voie de la mesure que les besoins se pose et la conception de mandat.
Lorsque l'on expose les membres de demander vous-même si vous exposer à la représentation des choix ou à l'abstraction des choix. La première est quelque chose que vous voulez éviter qu'il va présenter à beaucoup de dépendances sur la représentation réelle plutôt que c'est les comportements observables.
En règle générale j'essaie d'éviter de méthode de remplacement des implémentations par sous-classement, il est facile de bousiller la logique. Déclarer abstraite, les méthodes protected si vous avez l'intention pour qu'il soit remplacé.
Également utiliser le @Override annotation lors de la substitution de garder les choses de rupture lorsque vous refactoriser.
La réalité est un peu plus compliqué qu'une simple grille affiche. La grille permet de savoir si un accès est permis, mais de ce qui constitue exactement un accès? Aussi, les niveaux d'accès interagir avec les classes imbriquées et l'héritage de façon complexe.
L'accès "par défaut" (spécifié par l'absence d'un mot clé) est aussi appelé colis-privé. Exception: dans une interface, pas de modificateur de moyens d'accès public; les modificateurs d'autres que publics sont interdits. Enum les constantes sont toujours publiques.
Résumé
C'est l'accès à un membre avec ce spécificateur d'accès autorisé?
- Membre est -
private
: Seulement si le membre est définie à l'intérieur de la même classe que le code appelant. - Membre est colis privé: Seulement si le code d'appel est à l'intérieur du membre immédiatement en joignant paquet.
- Membre est -
protected
: Même paquet, ou si le membre est défini dans une super-classe de la classe contenant le code d'appel. - Membre est -
public
: Oui.
Ce spécificateurs d'accès s'appliquent à
Les variables locales et les paramètres formels ne peuvent pas prendre des spécificateurs d'accès. Depuis qu'ils sont par nature inaccessible à l'extérieur selon les règles de portée, ils sont effectivement privés.
Pour les classes dans le haut de la portée, seulement public
et colis-privé sont autorisés. Ce choix de conception est sans doute parce qu' protected
et private
serait redondant au niveau du package (il n'y a pas de succession de paquets).
Tous les spécificateurs d'accès sont possibles sur les membres de classe (constructeurs, les méthodes et les fonctions membres statiques, classes imbriquées).
Connexes: Classe Java Accessibilité
Afin
Les spécificateurs d'accès peuvent être strictement commandé
public > protected > package-privé > privé
ce qui signifie que public
fournit la plupart des accès, private
le moins. Toute référence possible à un membre privé est également valable pour un colis-privé; toute référence à un colis-privé membre est valide sur un membre protégé, et ainsi de suite. (Donnant accès à des membres protégés à d'autres classes du même package a été considéré comme une erreur.)
Notes
-
Une classe de méthodes sont autorisés à accéder aux membres privés d'autres objets de la même classe. Plus précisément, une méthode de classe C peut accéder aux membres privés de C sur les objets d'une sous-classe de C. Java ne supporte pas de restriction d'accès par exemple, seulement par la classe. (Comparez avec la Scala, qui prend en charge l'aide d'
private[this]
.) - Vous avez besoin d'accéder à un constructeur pour construire un objet. Ainsi, si tous les constructeurs sont privées, la classe ne peut être construit par le code de vie à l'intérieur de la classe (généralement statiques méthodes de fabrique ou variable statique initialiseurs). De même pour les colis-privé ou protégé de constructeurs.
- Seul le fait d'avoir privé les constructeurs signifie également que la classe ne peut pas être sous-classé à l'extérieur, depuis Java nécessite une sous-classe de constructeurs pour implicitement ou explicitement appeler un constructeur de la superclasse. (Cependant, il peut contenir une classe imbriquée qui sous-classes).
Les classes internes
Vous avez également à considérer imbriquée étendues, telles que les classes internes. Un exemple de la complexité, c'est que les classes internes de membres, qui peuvent eux-mêmes prendre des modificateurs d'accès. Vous pouvez donc avoir une intérieure privée de la classe avec un membre du public; le député peut-il être consulté? (Voir ci-dessous). La règle générale est d'examiner la portée et de penser de manière récursive pour voir si vous pouvez accéder à chaque niveau.
Cependant, c'est assez compliqué, et pour plus de détails, consulter le Langage Java Spécification. (Oui, il y a eu des bugs du compilateur dans le passé.)
Pour un avant-goût de la façon dont celles-ci interagissent, prenons cet exemple. Il est possible de "fuite" intérieure privée les classes; c'est généralement un avertissement:
class Test {
public static void main(final String ... args) {
System.out.println(Example.leakPrivateClass()); // OK
Example.leakPrivateClass().secretMethod(); // error
}
}
class Example {
private static class NestedClass {
public void secretMethod() {
System.out.println("Hello");
}
}
public static NestedClass leakPrivateClass() {
return new NestedClass();
}
}
Sortie du compilateur:
Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
Example.leakPrivateClass().secretMethod(); // error
^
1 error
Certaines questions connexes: