Précédent   Forum des professionnels en informatique > Java > Général Java > Débuter
Débuter Forum d'entraide pour bien débuter avec Java
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 21/08/2006, 09h53   #1
Membre habitué
 
Inscription : septembre 2005
Messages : 747
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 747
Points : 132
Points : 132
Par défaut Classes, méthodes private

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
Premium est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/08/2006, 10h10   #2
in
Membre Expert
 
Avatar de in
 
Inscription : avril 2003
Messages : 1 609
Détails du profil
Informations personnelles :
Localisation : France, Finistère (Bretagne)

Informations forums :
Inscription : avril 2003
Messages : 1 609
Points : 1 564
Points : 1 564
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 ...
__________________
"If email had been around before the telephone was invented, people would have said, 'Hey, forget email! With this new telephone invention I can actually talk to people!"

Besoin d'une nouvelle méthode pour développer ? -> http://www.la-rache.com/
in est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/08/2006, 11h13   #3
Membre émérite
 
Inscription : mars 2002
Messages : 969
Détails du profil
Informations personnelles :
Âge : 39

Informations forums :
Inscription : mars 2002
Messages : 969
Points : 964
Points : 964
Envoyer un message via MSN à thibaut
Citation:
Envoyé par in
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)[...]
Malheureusement une erreur s'est glissée:

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.

A+
thibaut est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/08/2006, 11h36   #4
in
Membre Expert
 
Avatar de in
 
Inscription : avril 2003
Messages : 1 609
Détails du profil
Informations personnelles :
Localisation : France, Finistère (Bretagne)

Informations forums :
Inscription : avril 2003
Messages : 1 609
Points : 1 564
Points : 1 564
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 ...
__________________
"If email had been around before the telephone was invented, people would have said, 'Hey, forget email! With this new telephone invention I can actually talk to people!"

Besoin d'une nouvelle méthode pour développer ? -> http://www.la-rache.com/
in est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/08/2006, 12h03   #5
Membre confirmé
 
Inscription : juin 2006
Messages : 194
Détails du profil
Informations personnelles :
Localisation : France, Ille et Vilaine (Bretagne)

Informations forums :
Inscription : juin 2006
Messages : 194
Points : 221
Points : 221
Citation:
Envoyé par Premium
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
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.

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.
had35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/08/2006, 12h11   #6
Membre émérite
 
Inscription : mars 2002
Messages : 969
Détails du profil
Informations personnelles :
Âge : 39

Informations forums :
Inscription : mars 2002
Messages : 969
Points : 964
Points : 964
Envoyer un message via MSN à thibaut
Citation:
Envoyé par had35
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.
Faux, une classe interne peut tout à fait être définie protected, public ou friendly.

Citation:
Envoyé par had35
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.
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...

A+
thibaut est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/08/2006, 13h07   #7
Rédacteur/Modérateur
 
Avatar de adiGuba
 
Homme
Développeur Java/Web
Inscription : avril 2002
Messages : 12 460
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Corse (Corse)

Informations professionnelles :
Activité : Développeur Java/Web
Secteur : Transports

Informations forums :
Inscription : avril 2002
Messages : 12 460
Points : 19 447
Points : 19 447
Salut,

Citation:
Envoyé par thibaut
Faux, une classe interne peut tout à fait être définie protected, public ou friendly.
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).


Citation:
Envoyé par thibaut
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...
Oui et non...

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 :
Code :
1
2
Object o = new Integer(5);
String s = o.toString();
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.

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 :
Code :
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();
    }
}
Pour rappel Integer.MAX_VALUE vaut quand même : 2147483647.

J'obtiens les résultats suivant :
Code :
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
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.

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++
__________________
adiGuba [ tutoriels | blog | twitter ] Rédacteur/Modérateur Java Présentation de Java SE 7 (commentaires)
adiGuba est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/08/2006, 14h49   #8
Membre confirmé
 
Inscription : juin 2006
Messages : 194
Détails du profil
Informations personnelles :
Localisation : France, Ille et Vilaine (Bretagne)

Informations forums :
Inscription : juin 2006
Messages : 194
Points : 221
Points : 221
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 :
Citation:
Envoyé par had35
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.
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.

Un exemple ici : http://www.developpez.net/forums/sho...57&postcount=8
had35 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 07h40.


 
 
 
 
Partenaires

Hébergement Web