Bonjour,
est-ce que quelqu'un pourrait m'expliquer quant il faut mettre les classes et méthodes private?
Je voudrais aussi savoir l'intéret de mettre les constructeurs protected
Merci
Bonjour,
est-ce que quelqu'un pourrait m'expliquer quant il faut mettre les classes et méthodes private?
Je voudrais aussi savoir l'intéret de mettre les constructeurs protected
Merci
tout dépend de comment tu veux qu'on accède à ton code.
Si tu veux qu'on puisse les instancier, appeler des méthodes dessus ...
Public c'est pour que se soit accessible de partout
Protected l'accès est réservé aux classes du meme package
Private ben l'acces est interdit
(j'espere que je ne me trompe pas)
Pour ta question concernant le constructeur protected :
et bien seulement les classes du meme package pourront instancier cet objet.
Par exemple dans le cas d'une classe mère protected, une classe fille pourra utiliser le constructeur parent ... mais en dehors du package, aucune classe ne pourra instancier cet objet
je sais pas si je suis clair, mais bon dans tous les cours sur java tu trouveras des explications sur la visibilité des objets ...
Malheureusement une erreur s'est glissée:Envoyé par in
public l'accés à une méthode public est garanti à toute classe.
protected l'accés à une méthode protected est garanti à toute classe dans la package et toute sous-classe dans la hiérarchie d'héritage (et oui c'est bizarre).
friendly (sans aucun modificateur) l'accés à une méthode friendly est garanti à toute classe dans la package.
private l'accés est garanti à la classe où la méthode est définie uniquement.
Les même régles s'appliquent quand un modificateur est placé devant un atrribut ou une définition de classe ou de classe interne.
L'attribut static peut être combiné avec les modificateurs pré-cités pour permettre un accés à la méthode, classe interne ou attribut sans instance de classe.
Il faut en général utiliser les modificateurs de la façon suivante:
- private : quand on veut "masquer" un comportement d'un classe, un peu comme une boite noire, seul compte dans ce cas les entrées et la sortie.
- protected est similaire à private mais dans le cas d'un héritage (pour que la méthode soit accéssible aux sous-classes)
- friendly pour étendre la visibilité aux classes du package.
- public pour tous.
Alors à la lumière de ces constatations quelques régles générales se dégagent:
- public est à utiliser avec parcimonie, le moins souvent possible.
- toute méthode qui n'est accédée que dans la classe doit être définie private.
- toute méthode qui n'est accédée que par la classe ou une de ses sous-classes doit être définie protected.
- toute méthode accédée dans un package doit être définie friendly ou éventuellemet protected (mais moi je réserve protected aux cas d'héritage pour pas qu'il y ait de confusions).
Ces régles sont applicables pour des classes internes et des attributs bien évidemment.
Plus d'exemples pour apprendre à programmer avec Java voir les tutoriels et cours Java : http://java.developpez.com/cours/
A+
en fait je parlait de la visibilité au niveau des classes.
mais merci de tes explications qui sont bien plus utiles et claires que les miennes ...
Seules les classes internes peuvent être déclarées private. On le fera lorsqu'aucune instance de cette classe interne n'a pas besoin d'être manipulée hors de la classe qui l'encapsule.Envoyé par Premium
Pareil pour les méthodes private. Il y a un élément supplémentaire, les appels de méthodes private ou final sont théoriquement plus rapides que les appels de méthodes public ou protected.
Un constructeur, ou toute autre méthode, sera protected lorsqu'il est uniquement destiné à être redéfinie. Par exemple, on pourrait imaginer un Singleton dont on voudrait laisser la possibilité de redéfinir le constructeur. Attention néanmoins, l'utilisation de protected, contrairement à ce qu'on pourrait penser, n'est pas sûre car la visibilité peut être relevée à public lors de la redéfinition. protected doit donc être vu seulement comme une sorte de tag.
Faux, une classe interne peut tout à fait être définie protected, public ou friendly.Envoyé par had35
Tout cela reste à prouver. Je ne suis pas certains quer la difference de traitement sur un appel d'une méthode de classe public ou privée soit significatif...Envoyé par had35
A+
Salut,
Il ne dit pas le contraire !!! Il dit juste qu'une classe interne PEUT être private (ou protected d'ailleurs). Chose qu'on ne peut pas faire avec une classe "normal" (si une classe normal est private on ne pourrait l'utiliser nulle part).Envoyé par thibaut
Oui et non...Envoyé par thibaut
En réalité l'appel d'une méthode public a un certain coût, puisque comme elle peut être redéfinit dans une classe fille, il faut vérifier le type réel de l'objet pour appeler la bonne méthode.
Par exemple lorsqu'on fait ceci :
C'est bien la méthode toString() de Integer qui est appelé, et non pas celle de Object. C'est un appel de méthode dynamique, et ce type de fonctionnalité a un coût.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 Object o = new Integer(5); String s = o.toString();
A l'inverse les méthodes final ou private ne peuvent pas être redéfinit dans les classes filles. Donc la JVM n'a pas besoin de rechercher le type exact de l'objet et procède directement à un appel statique avec d'éventuelle optimisation (inlining de la méthode, etc.).
Toutefois, la différence n'est vraiment visible que pour un très grand nombre d'appel de méthode, et surtout les JVM récentes (Java 1.2 et +) mettent en place plusieurs mécanismes d'optimisation :
Comme la JVM s'occupe du chargement des classes, elle connaît exactement la hiérarchie des classes, et peut déterminer qu'une classe ne possède pas de classe fille, ou qu'une certaine méthode n'est jamais redéfinit dans ses classes filles. Elle peut donc optimiser les méthodes public de la même manière que les méthodes private ou final, en sachant que si une classe fille est chargée en mémoire, cela nécessiterai de recompiler le code...
Le code suivant permet de mettre cela en évidence :
Pour rappel Integer.MAX_VALUE vaut quand même : 2147483647.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public class Main { private int privateMethod(int v) { return v + 1; } public final int publicFinalMethod(int v) { return v + 1; } public int publicMethod(int v) { return v + 1; } public void test() { int MAX = Integer.MAX_VALUE; long start, end; // Une boucle vide afin d'éviter que des optimisations // modifie les résultats du premier test for (int i=0; i<MAX; i++) ; start = System.currentTimeMillis(); for (int i=0; i<MAX; i++) { privateMethod(i); } end = System.currentTimeMillis(); System.out.println("\tprivateMethod() : " + (end-start)); start = System.currentTimeMillis(); for (int i=0; i<MAX; i++) { publicMethod(i); } end = System.currentTimeMillis(); System.out.println("\tpublicMethod() : " + (end-start)); start = System.currentTimeMillis(); for (int i=0; i<MAX; i++) { publicFinalMethod(i); } end = System.currentTimeMillis(); System.out.println("\tpublicFinalMethod() : " + (end-start)); } public static void main(String[] args) { System.out.println("Test Direct :"); new Main().test(); System.out.println(); System.out.println("Test avec une classe Fille :"); new Main(){ // classe anonyme Main$1 // Ne redéfinit pas la méthode publicMethod() ! @Override public String toString() { return "hello"; } }.test(); System.out.println(); System.out.println("Test avec une classe Fille qui redéfinit publicMethod() :"); new Main(){ // classe anonyme Main$2 @Override public int publicMethod(int v) { return 0; } }.test(); System.out.println(); System.out.println("Test Direct (bis) :"); new Main().test(); } }
J'obtiens les résultats suivant :
Lors du premier test, je n'ai qu'une classe de chargée (Main), et le temps d'exécution des boucles est quasiment identique à moins de 100 ms près.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 Test Direct : privateMethod() : 3672 publicMethod() : 3750 publicFinalMethod() : 3657 Test avec une classe Fille : privateMethod() : 3672 publicMethod() : 3765 publicFinalMethod() : 3657 Test avec une classe Fille qui redéfinit publicMethod() : privateMethod() : 3672 publicMethod() : 38986 publicFinalMethod() : 3687 Test Direct (bis) : privateMethod() : 3672 publicMethod() : 40063 publicFinalMethod() : 3703
Dans le second test, j'ai deux classes chargées : Main et sa classe fille anonyme Main$1, et le test s'effectue sur cette dernière. Toutefois comme cette dernière ne surcharge pas la méthode publicMethod(), cela n'impacte quasiment pas les résultat.
Dans le troisième test, j'ai une nouvelle classes anonymes de chargé : Main$2 qui redéfinit la méthode publicMethod(), cela oblige la machine virtuelle a vérifier dynamiquement le type réel de l'objet à chaque appel de la méthode. Du coup le temps d'exécution explose carrément et monte à près de 40 secondes contre un peu moins de 4 précédemment. On voit bien là le coût de l'appel dynamique...
Enfin le quatrième test renouvelle un test avec la classe parente (Main), mais comme il y a plusieurs classes filles (Main$1 et Main$2) dont une redéfinit publicMethod(), l'appel dynamique est de nouveau utilisé, et on obtient les même résultat qu'au 3ieme test...
Bref : les appels de méthode private et final sont plus rapide car il ne sont jamais exécuté en dynamique mais toujours en statique...
Toutefois, la différence entre les deux est vraiment minime (environ 0.00002 ms si je ne me trompe pas) et ne se ressent que sur un très grand nombre d'appel de méthode (2 milliards en l'occurrence).
a++
Merci adiGuba pour ces superbes précisions.
Je vais moi aussi apporter une précision supplémentaire, bien que plus modeste
J'ai simplifié un aspect de l'encapsulation des classes lorsque j'ai écrit ceci :
En réalité, lorsqu'une classe interne est private, ce n'est pas réellement ses instances qui deviennents inaccessibles mais le type définit par la classe interne. Cela revient donc au même qu'écrire une classe anonyme (du moins concernant la visibilité du type), c'est-à-dire qu'une instance d'une classe interne private peut quand même être récupérée à condition qu'elle hérite d'une classe ou d'une interface publique.Envoyé par had35
Un exemple ici : http://www.developpez.net/forums/sho...57&postcount=8
Partager